itadded makefile, tomb source, doc update - coffin - secure lan file storage on a device Err parazyd.org 70 hgit clone git://parazyd.org/coffin.git URL:git://parazyd.org/coffin.git parazyd.org 70 1Log /git/coffin/log.gph parazyd.org 70 1Files /git/coffin/files.gph parazyd.org 70 1Refs /git/coffin/refs.gph parazyd.org 70 1Submodules /git/coffin/file/.gitmodules.gph parazyd.org 70 1README /git/coffin/file/README.md.gph parazyd.org 70 1LICENSE /git/coffin/file/LICENSE.gph parazyd.org 70 i--- Err parazyd.org 70 1commit 93560963b2413c846da85efd2596c8a69cff9f77 /git/coffin/commit/93560963b2413c846da85efd2596c8a69cff9f77.gph parazyd.org 70 1parent f7a9f52b2508eff9381a644bb13e87f9ed7b6f9c /git/coffin/commit/f7a9f52b2508eff9381a644bb13e87f9ed7b6f9c.gph parazyd.org 70 hAuthor: parazyd URL:mailto:parazyd@dyne.org parazyd.org 70 iDate: Mon, 28 Mar 2016 21:13:58 +0200 Err parazyd.org 70 i Err parazyd.org 70 iadded makefile, tomb source, doc update Err parazyd.org 70 i Err parazyd.org 70 iDiffstat: Err parazyd.org 70 i A Makefile | 10 ++++++++++ Err parazyd.org 70 i M README.md | 19 +++++++++++++++---- Err parazyd.org 70 i A src/tomb/.gitignore | 11 +++++++++++ Err parazyd.org 70 i A src/tomb/Makefile | 26 ++++++++++++++++++++++++++ Err parazyd.org 70 i A src/tomb/doc/Makefile.am | 6 ++++++ Err parazyd.org 70 i A src/tomb/doc/tomb.1 | 467 +++++++++++++++++++++++++++++++ Err parazyd.org 70 i A src/tomb/kdf-keys/.gitignore | 4 ++++ Err parazyd.org 70 i A src/tomb/kdf-keys/Makefile | 18 ++++++++++++++++++ Err parazyd.org 70 i A src/tomb/kdf-keys/README | 27 +++++++++++++++++++++++++++ Err parazyd.org 70 i A src/tomb/kdf-keys/benchmark.c | 59 +++++++++++++++++++++++++++++++ Err parazyd.org 70 i A src/tomb/kdf-keys/gen_salt.c | 39 +++++++++++++++++++++++++++++++ Err parazyd.org 70 i A src/tomb/kdf-keys/hexencode.c | 49 +++++++++++++++++++++++++++++++ Err parazyd.org 70 i A src/tomb/kdf-keys/pbkdf2.c | 144 +++++++++++++++++++++++++++++++ Err parazyd.org 70 i A src/tomb/kdf-keys/test.sh | 22 ++++++++++++++++++++++ Err parazyd.org 70 i A src/tomb/kdf-keys/test.txt | 0 Err parazyd.org 70 i A src/tomb/tomb | 2834 +++++++++++++++++++++++++++++++ Err parazyd.org 70 i Err parazyd.org 70 i16 files changed, 3731 insertions(+), 4 deletions(-) Err parazyd.org 70 i--- Err parazyd.org 70 1diff --git a/Makefile b/Makefile /git/coffin/file/Makefile.gph parazyd.org 70 it@@ -0,0 +1,10 @@ Err parazyd.org 70 i+all: Err parazyd.org 70 i+ make -C src/tomb/kdf-keys Err parazyd.org 70 i+ Err parazyd.org 70 i+install: Err parazyd.org 70 i+ make -C src/tomb install Err parazyd.org 70 i+ make -C src/tomb/kdf-keys install Err parazyd.org 70 i+ @./config.sh Err parazyd.org 70 i+ Err parazyd.org 70 i+clean: Err parazyd.org 70 i+ make -C src/tomb/kdf-keys clean Err parazyd.org 70 1diff --git a/README.md b/README.md /git/coffin/file/README.md.gph parazyd.org 70 it@@ -11,15 +11,26 @@ Now, you are able to access your files on the LAN. Err parazyd.org 70 i Once you plug in your key again, that same tomb will be closed and your Err parazyd.org 70 i files are once again unreadable. Err parazyd.org 70 i Err parazyd.org 70 i+## Installation Err parazyd.org 70 i+Install the needed dependencies, some from the following list may vary Err parazyd.org 70 i+depending on the distro you are using: Err parazyd.org 70 i+``` Err parazyd.org 70 i+zsh cryptsetup libgcrypt20-dev apache2 wipe sshfs inotify-tools Err parazyd.org 70 i+pinentry-curses pwgen gettext haveged sudo Err parazyd.org 70 i+``` Err parazyd.org 70 i+ Err parazyd.org 70 i+Clone this repository to the device you will be using. Err parazyd.org 70 i+ Err parazyd.org 70 i+Run `make` in order to compile tomb's KDF modules. Err parazyd.org 70 i+ Err parazyd.org 70 i+Run `make install` as root in order to install and configure your Err parazyd.org 70 i+device. It will install all the required dependencies needed as well. Err parazyd.org 70 i+ Err parazyd.org 70 i ## Notes Err parazyd.org 70 i * `gmakehook` can be used to create coffin hooks in a more user-friendly Err parazyd.org 70 i manner. It is a GUI (zenity) helper script. Err parazyd.org 70 i Err parazyd.org 70 i ## Usage Err parazyd.org 70 i Err parazyd.org 70 i-## Installation Err parazyd.org 70 i-Clone this git repository to your device, and run Err parazyd.org 70 i-`make` followed by `make install` Err parazyd.org 70 i- Err parazyd.org 70 i ## Troubleshooting Err parazyd.org 70 i Err parazyd.org 70 1diff --git a/src/tomb/.gitignore b/src/tomb/.gitignore /git/coffin/file/src/tomb/.gitignore.gph parazyd.org 70 it@@ -0,0 +1,11 @@ Err parazyd.org 70 i+\#* Err parazyd.org 70 i+.\#* Err parazyd.org 70 i+*~ Err parazyd.org 70 i+*.o Err parazyd.org 70 i+tomb-askpass Err parazyd.org 70 i+tomb-status Err parazyd.org 70 i+doc/web/public Err parazyd.org 70 i+doc/web/dyne Err parazyd.org 70 i+share/gtkrc Err parazyd.org 70 i+.*.sw? Err parazyd.org 70 i+*.mo Err parazyd.org 70 1diff --git a/src/tomb/Makefile b/src/tomb/Makefile /git/coffin/file/src/tomb/Makefile.gph parazyd.org 70 it@@ -0,0 +1,26 @@ Err parazyd.org 70 i+PROG = tomb Err parazyd.org 70 i+PREFIX ?= /usr/local Err parazyd.org 70 i+MANDIR ?= ${PREFIX}/share/man Err parazyd.org 70 i+ Err parazyd.org 70 i+all: Err parazyd.org 70 i+ @echo Err parazyd.org 70 i+ @echo "Tomb is a script and does not need compilation, it can be simply executed." Err parazyd.org 70 i+ @echo Err parazyd.org 70 i+ @echo "To install it in /usr/local together with its manpage use 'make install'." Err parazyd.org 70 i+ @echo Err parazyd.org 70 i+ @echo "To run Tomb one needs to have some tools installed on the system:" Err parazyd.org 70 i+ @echo "Sudo, cryptsetup, pinentry and gnupg. Also wipe is recommended." Err parazyd.org 70 i+ @echo Err parazyd.org 70 i+ Err parazyd.org 70 i+install: Err parazyd.org 70 i+ install -Dm755 ${PROG} ${DESTDIR}${PREFIX}/bin/${PROG} Err parazyd.org 70 i+ install -Dm644 doc/${PROG}.1 ${DESTDIR}${MANDIR}/man1/${PROG}.1 Err parazyd.org 70 i+ @echo Err parazyd.org 70 i+ @echo "Tomb is installed succesfully. To install language translations, make sure" Err parazyd.org 70 i+ @echo "gettext is also installed, then 'cd extras/translations' and 'make install' there." Err parazyd.org 70 i+ @echo Err parazyd.org 70 i+ @echo "Look around the extras/ directory, it contains other interesting modules." Err parazyd.org 70 i+ @echo Err parazyd.org 70 i+ Err parazyd.org 70 i+test: Err parazyd.org 70 i+ make -C extras/test Err parazyd.org 70 1diff --git a/src/tomb/doc/Makefile.am b/src/tomb/doc/Makefile.am /git/coffin/file/src/tomb/doc/Makefile.am.gph parazyd.org 70 it@@ -0,0 +1,6 @@ Err parazyd.org 70 i+ Err parazyd.org 70 i+man_MANS = tomb.1 tomb-open.1 tomb-status.1 Err parazyd.org 70 i+ Err parazyd.org 70 i+EXTRA_DIST = tomb.1 tomb-open.1 tomb-status.1 Luks_on_disk_format.pdf \ Err parazyd.org 70 i+ New_methods_in_HD_encryption.pdf TKS1-draft.pdf Err parazyd.org 70 i+ Err parazyd.org 70 1diff --git a/src/tomb/doc/tomb.1 b/src/tomb/doc/tomb.1 /git/coffin/file/src/tomb/doc/tomb.1.gph parazyd.org 70 it@@ -0,0 +1,467 @@ Err parazyd.org 70 i+.TH tomb 1 "November 26, 2014" "tomb" Err parazyd.org 70 i+ Err parazyd.org 70 i+.SH NAME Err parazyd.org 70 i+Tomb \- the Crypto Undertaker Err parazyd.org 70 i+ Err parazyd.org 70 i+.SH SYNOPSIS Err parazyd.org 70 i+.B Err parazyd.org 70 i+.IP "tomb [options] command [arguments]" Err parazyd.org 70 i+ Err parazyd.org 70 i+.SH DESCRIPTION Err parazyd.org 70 i+ Err parazyd.org 70 i+Tomb is an application to manage the creation and access of encrypted Err parazyd.org 70 i+storage files: it can be operated from commandline and it can Err parazyd.org 70 i+integrate with a user's graphical desktop. Err parazyd.org 70 i+ Err parazyd.org 70 i+Tomb generates encrypted storage files to be opened and closed using Err parazyd.org 70 i+their associated keys, which are also protected with a password chosen Err parazyd.org 70 i+by the user. To create, open and close tombs a user will need super Err parazyd.org 70 i+user rights to execute the tomb commandline utility. Err parazyd.org 70 i+ Err parazyd.org 70 i+A tomb is like a locked folder that can be safely transported and Err parazyd.org 70 i+hidden in a filesystem; it encourages users to keep their keys Err parazyd.org 70 i+separate from tombs, for instance keeping a tomb file on your computer Err parazyd.org 70 i+harddisk and its key file on a USB stick. Err parazyd.org 70 i+ Err parazyd.org 70 i+ Err parazyd.org 70 i+.SH COMMANDS Err parazyd.org 70 i+ Err parazyd.org 70 i+.B Err parazyd.org 70 i+.IP "dig" Err parazyd.org 70 i+Generates a file that can be used as a tomb and will occupy as much Err parazyd.org 70 i+space as its desired initial size, the unlocked \fI.tomb\fR file can Err parazyd.org 70 i+then be locked using a \fIkey\fR. It takes a mandatory \fI-s\fR option which is Err parazyd.org 70 i+the size in megabytes (MiB). Tombs are digged using Err parazyd.org 70 i+low-quality random data (/dev/urandom). Err parazyd.org 70 i+ Err parazyd.org 70 i+.B Err parazyd.org 70 i+.IP "forge" Err parazyd.org 70 i+Creates a new \fIkey\fR and prompts the user for a \fIpassword\fR to Err parazyd.org 70 i+protect its usage. This operation requires high quality random data Err parazyd.org 70 i+(/dev/random) which can take quite some time to be gathered on a Err parazyd.org 70 i+server: it works better on a desktop where the mouse can be moved Err parazyd.org 70 i+around for entropy. The default cipher to protect the key is AES256, a Err parazyd.org 70 i+custom one can be specified using the \fI-o\fR option, for a list of Err parazyd.org 70 i+supported ciphers use \fI-v\fR. For additional protection against Err parazyd.org 70 i+dictionary attacks on keys, the (experimental) \fI--kdf\fR option can Err parazyd.org 70 i+be used when forging a key, making sure that the \fItomb-kdb-pbkdf2\fR Err parazyd.org 70 i+binaries in \fIextras/kdf\fR were compiled and installed on the Err parazyd.org 70 i+system. Err parazyd.org 70 i+ Err parazyd.org 70 i+.B Err parazyd.org 70 i+.IP "lock" Err parazyd.org 70 i+Initializes and locks an empty tomb (made with \fIdig\fR) using a key Err parazyd.org 70 i+(made with \fIforge\fR), making it ready for usage. After this Err parazyd.org 70 i+operation, the tomb can only be opened in possession of the key and Err parazyd.org 70 i+knowing its password. As in any other command requiring a key, the Err parazyd.org 70 i+option \fI-k\fR should be used to specify a key file. The \fI-o\fR Err parazyd.org 70 i+option can be used to specify the cipher specification: default is Err parazyd.org 70 i+"aes-xts-plain64:sha256", old versions of Tomb used "aes-cbc-essiv:sha256". Err parazyd.org 70 i+If you are looking for something exotic, also try "serpent-xts-plain64". Err parazyd.org 70 i+More options may be found in cryptsetup(8) and Linux documentation. Err parazyd.org 70 i+This operation requires root privileges to loopback mount, format the tomb (using Err parazyd.org 70 i+LUKS and Ext4), then set the key in its first LUKS slot. Err parazyd.org 70 i+ Err parazyd.org 70 i+.B Err parazyd.org 70 i+.IP "open" Err parazyd.org 70 i+Opens an existing \fI.tomb\fR (first argument) using a key (\fI-k\fR), Err parazyd.org 70 i+if a second argument is given it will indicate the \fImountpoint\fR Err parazyd.org 70 i+where the tomb should be made accessible, else the tomb is mounted in Err parazyd.org 70 i+a directory inside /media (if not available it uses /run/media/$USER). Err parazyd.org 70 i+The option \fI-o\fR can be used to pass mount(8) options Err parazyd.org 70 i+(default: rw,noatime,nodev). Err parazyd.org 70 i+ Err parazyd.org 70 i+.B Err parazyd.org 70 i+.IP "list" Err parazyd.org 70 i+List all the tombs found open, including information about the time Err parazyd.org 70 i+they were opened and the hooks that they mounted. If the first Err parazyd.org 70 i+argument is present, then shows only the tomb named that way or Err parazyd.org 70 i+returns an error if it's not found. If the option Err parazyd.org 70 i+\fI--get-mountpoint\fR is used then print a simple list of currently Err parazyd.org 70 i+open tomb mountpoint paths. Err parazyd.org 70 i+ Err parazyd.org 70 i+.B Err parazyd.org 70 i+.IP "index" Err parazyd.org 70 i+Creates or updates the search indexes of all tombs currently open: Err parazyd.org 70 i+enables use of the \fIsearch\fR command using simple word patterns on Err parazyd.org 70 i+file names. Indexes are created using mlocate's updatedb(8) and Err parazyd.org 70 i+swish-e(1) if they are found on the system. Indexes allow to search Err parazyd.org 70 i+very fast for filenames and contents inside a tomb, they are stored Err parazyd.org 70 i+inside it and are not accessible if the Tomb is closed. To avoid Err parazyd.org 70 i+indexing a specific tomb simply touch a \fI.noindex\fR file in it. Err parazyd.org 70 i+ Err parazyd.org 70 i+.B Err parazyd.org 70 i+.IP "search" Err parazyd.org 70 i+Takes any string as argument and searches for them through all tombs Err parazyd.org 70 i+currently open and previously indexed using the \fIindex\fR command. Err parazyd.org 70 i+The search matches filenames if mlocate is installed and then also Err parazyd.org 70 i+file contents if swish++ is present on the system, results are listed Err parazyd.org 70 i+on the console. Err parazyd.org 70 i+ Err parazyd.org 70 i+.B Err parazyd.org 70 i+.IP "close" Err parazyd.org 70 i+Closes a currently open tomb. If more tombs are open, the first Err parazyd.org 70 i+argument should be used to specify the name of the tomb to be closed, Err parazyd.org 70 i+or \fIall\fR to close all currently open tombs. This command fails if Err parazyd.org 70 i+the tomb is in use by running processes (to force close, see Err parazyd.org 70 i+\fIslam\fR below). Err parazyd.org 70 i+ Err parazyd.org 70 i+.B Err parazyd.org 70 i+.IP "slam" Err parazyd.org 70 i+Closes a tomb like the command \fIclose\fR does, but it doesn't fail Err parazyd.org 70 i+even if the tomb is in use by other application processes: it looks Err parazyd.org 70 i+for and violently kills \-9 each of them. This command may Err parazyd.org 70 i+provoke unsaved data loss, but assists users to face surprise Err parazyd.org 70 i+situations. Err parazyd.org 70 i+ Err parazyd.org 70 i+ Err parazyd.org 70 i+.B Err parazyd.org 70 i+.IP "passwd" Err parazyd.org 70 i+Changes the password protecting a key file specified using Err parazyd.org 70 i+\fI-k\fR. The user will need to know the key's current password, then Err parazyd.org 70 i+its content will be decoded and reencoded using the new one. This Err parazyd.org 70 i+action can't be forced if the current password is not known. If the Err parazyd.org 70 i+key file is broken (missing headers) this function also attempts its Err parazyd.org 70 i+recovery. Err parazyd.org 70 i+ Err parazyd.org 70 i+.B Err parazyd.org 70 i+.IP "setkey" Err parazyd.org 70 i+Changes the key file that locks a tomb, substituting the old one with Err parazyd.org 70 i+a new one. Both the old and the new key files are needed for this Err parazyd.org 70 i+operation and their passwords must be known. The new key must be Err parazyd.org 70 i+specified using the \fI-k\fR option, the first argument should be the old Err parazyd.org 70 i+key and the second and last argument the tomb file. Err parazyd.org 70 i+ Err parazyd.org 70 i+.B Err parazyd.org 70 i+.IP "resize" Err parazyd.org 70 i+Increase the size of a tomb file to the amount specified by the Err parazyd.org 70 i+\fI-s\fR option, which is the new size in megabytes (MiB). Full access to the tomb using Err parazyd.org 70 i+a key (\fI-k\fR) and its password is required. Tombs can only grow and Err parazyd.org 70 i+can never be made smaller. This command makes use of the cryptsetup(8) Err parazyd.org 70 i+resize feature and the resize2fs command: its much more practical than Err parazyd.org 70 i+creating a new tomb and moving everything into it. Err parazyd.org 70 i+ Err parazyd.org 70 i+.B Err parazyd.org 70 i+.IP "engrave" Err parazyd.org 70 i+This command transforms a tomb key into an image that can be printed Err parazyd.org 70 i+on paper and physically stored as backup, i.e. hidden in a book. It Err parazyd.org 70 i+Renders a QRCode of the tomb key, still protected by its password: a Err parazyd.org 70 i+PNG image (extension \fI.qr.png\fR) will be created in the current Err parazyd.org 70 i+directory and can be later printed (fits an A4 or Letter format). To Err parazyd.org 70 i+recover an engraved key one can use any QRCode reader on a smartphone: Err parazyd.org 70 i+save it into a file and then use that file as a key (\fI-k\fR). Err parazyd.org 70 i+ Err parazyd.org 70 i+.B Err parazyd.org 70 i+.IP "bury" Err parazyd.org 70 i+Hides a tomb key (\fI-k\fR) inside a \fIjpeg image\fR (first argument) Err parazyd.org 70 i+using \fIsteganography\fR: the image will change in a way that cannot Err parazyd.org 70 i+be noticed by human eye and hardly detected by data analysis. This Err parazyd.org 70 i+option is useful to backup tomb keys in unsuspected places; it depends Err parazyd.org 70 i+from the availability of \fIsteghide\fR. Err parazyd.org 70 i+ Err parazyd.org 70 i+.B Err parazyd.org 70 i+.IP "exhume" Err parazyd.org 70 i+This command recovers from jpeg images the keys that were previously Err parazyd.org 70 i+hidden into them using \fIbury\fR. Exhume requires a key filename Err parazyd.org 70 i+(\fI-k\fR) and a \fIjpeg image\fR file (first argument) known to be Err parazyd.org 70 i+containing a key. If the right key password is given, the key will be Err parazyd.org 70 i+exhumed. If the password is not known, it is very hard to verify if a Err parazyd.org 70 i+key is buried in any image or not. Err parazyd.org 70 i+ Err parazyd.org 70 i+.SH OPTIONS Err parazyd.org 70 i+.B Err parazyd.org 70 i+.B Err parazyd.org 70 i+.IP "-k \fI\fR" Err parazyd.org 70 i+For all operations requiring a key, this option specifies the location Err parazyd.org 70 i+of the key file to use. Arguments can also be \fIjpeg image\fR files Err parazyd.org 70 i+where keys have been hidden using the \fIbury\fR command, or text Err parazyd.org 70 i+files retrieved from \fIengraved\fR QR codes. If the \fIkeyfile\fR Err parazyd.org 70 i+argument is "-" (dash), Tomb will read the key from stdin (blocking). Err parazyd.org 70 i+.B Err parazyd.org 70 i+.IP "-n" Err parazyd.org 70 i+Skip processing of post-hooks and bind-hooks if found inside the tomb. Err parazyd.org 70 i+See the \fIHOOKS\fR section in this manual for more information. Err parazyd.org 70 i+.B Err parazyd.org 70 i+.IP "-o" Err parazyd.org 70 i+Manually specify mount options to be used when opening a tomb instead Err parazyd.org 70 i+of the default \fIrw,noatime,nodev\fR, i.e. to mount a tomb read-only Err parazyd.org 70 i+(ro) to prevent any modification of its data. Can also be used to Err parazyd.org 70 i+change the symmetric encryption algorithm for keys during \fIforge\fR Err parazyd.org 70 i+operations (default \fIAES256\fR) or the LUKS encryption method during Err parazyd.org 70 i+\fIlock\fR operations (default \fIaes-xts-plain64:sha256\fR). Err parazyd.org 70 i+.B Err parazyd.org 70 i+.IP "-f" Err parazyd.org 70 i+Force flag, currently used to override swap checks, might be Err parazyd.org 70 i+overriding more wimpy behaviours in future, but make sure you know Err parazyd.org 70 i+what you are doing if you force an operation. Err parazyd.org 70 i+.B Err parazyd.org 70 i+.IP "-s \fI\fR" Err parazyd.org 70 i+When digging or resizing a tomb, this option must be used to specify Err parazyd.org 70 i+the \fIsize\fR of the new file to be created. Units are megabytes (MiB). Err parazyd.org 70 i+.B Err parazyd.org 70 i+.IP "--kdf \fI\fR" Err parazyd.org 70 i+Activate the KDF feature against dictionary attacks when creating a Err parazyd.org 70 i+key: forces a delay of \fI\fR seconds every time this key is used. Err parazyd.org 70 i+You should keep in mind that the actual iteration count is calculated based on Err parazyd.org 70 i+the performance of the computer where you forge the key. Err parazyd.org 70 i+The argument must be an integer, so you cannot say \fI--kdf 0.3\fR for 300ms. Err parazyd.org 70 i+.B Err parazyd.org 70 i+.IP "-h" Err parazyd.org 70 i+Display a help text and quit. Err parazyd.org 70 i+.B Err parazyd.org 70 i+.IP "-v" Err parazyd.org 70 i+Display version and quit. Err parazyd.org 70 i+.B Err parazyd.org 70 i+.IP "-q" Err parazyd.org 70 i+Run more quietly Err parazyd.org 70 i+.B Err parazyd.org 70 i+.IP "-D" Err parazyd.org 70 i+Print more information while running, for debugging purposes Err parazyd.org 70 i+ Err parazyd.org 70 i+.SH DEV MODE Err parazyd.org 70 i+.B Err parazyd.org 70 i+.IP "--no-color" Err parazyd.org 70 i+Suppress colors in console output (needed for string parsing by Err parazyd.org 70 i+wrappers). Err parazyd.org 70 i+.B Err parazyd.org 70 i+.IP "--unsafe" Err parazyd.org 70 i+Enable using dev-mode arguments, i.e. to pass passwords from Err parazyd.org 70 i+commandline options. This is mostly used needed for execution by Err parazyd.org 70 i+wrappers and testing suite. Err parazyd.org 70 i+.B Err parazyd.org 70 i+.IP "--use-urandom" Err parazyd.org 70 i+Use an inferior quality random source to improve the speed of key Err parazyd.org 70 i+generation at the cost of security (needed for the testing suite). Err parazyd.org 70 i+.B Err parazyd.org 70 i+.IP "--tomb-pwd " Err parazyd.org 70 i+Use string as password when needed on tomb. Err parazyd.org 70 i+.B Err parazyd.org 70 i+.IP "--tomb-old-pwd " Err parazyd.org 70 i+Use string as old password when needed in tomb commands requiring Err parazyd.org 70 i+multiple keys, like \fIpasswd\fR or \fIsetkey\fR. Err parazyd.org 70 i+.B Err parazyd.org 70 i+.IP "-U" Err parazyd.org 70 i+Switch to this user ID when dropping privileges. Err parazyd.org 70 i+.B Err parazyd.org 70 i+.IP "-G" Err parazyd.org 70 i+Switch to this group ID when dropping privileges. Err parazyd.org 70 i+.B Err parazyd.org 70 i+.IP "-T" Err parazyd.org 70 i+Switch to this TTY terminal when dropping privileges. Err parazyd.org 70 i+ Err parazyd.org 70 i+.SH HOOKS Err parazyd.org 70 i+ Err parazyd.org 70 i+Hooks are special files that can be placed inside the tomb and trigger Err parazyd.org 70 i+actions when it is opened and closed; there are two kinds of such Err parazyd.org 70 i+files: \fIbind-hooks\fR and \fIpost-hooks\fR can be placed in the Err parazyd.org 70 i+base root of the tomb. Err parazyd.org 70 i+ Err parazyd.org 70 i+.B Err parazyd.org 70 i+.IP "bind-hooks" Err parazyd.org 70 i+This hook file consists of a simple two column list of files or Err parazyd.org 70 i+directories inside the tomb to be made directly accessible inside the Err parazyd.org 70 i+current user's home directory. Tomb will use the "mount \-o bind" Err parazyd.org 70 i+command to bind locations inside the tomb to locations found in $HOME Err parazyd.org 70 i+so in the first column are indicated paths relative to the tomb and in Err parazyd.org 70 i+the second column are indicated paths relative to $HOME contents, for Err parazyd.org 70 i+example: Err parazyd.org 70 i+.EX Err parazyd.org 70 i+ mail mail Err parazyd.org 70 i+ .gnupg .gnupg Err parazyd.org 70 i+ .fmrc .fetchmailrc Err parazyd.org 70 i+ .mozilla .mozilla Err parazyd.org 70 i+.EE Err parazyd.org 70 i+ Err parazyd.org 70 i+.B Err parazyd.org 70 i+.IP "post-hooks" Err parazyd.org 70 i+This hook file gets executed as user by tomb right after opening it; Err parazyd.org 70 i+it should be a regular shell script, starting with a shebang. Tomb Err parazyd.org 70 i+executes this hook as user (dropping root privileges) and giving it Err parazyd.org 70 i+two arguments: "$1" is "open" or "close" depending from the tomb Err parazyd.org 70 i+command given, "$2" is the full path to the mountpoint where the tomb Err parazyd.org 70 i+is open. Err parazyd.org 70 i+ Err parazyd.org 70 i+.SH PRIVILEGE ESCALATION Err parazyd.org 70 i+ Err parazyd.org 70 i+The tomb commandline tool needs to acquire super user rights to Err parazyd.org 70 i+execute most of its operations: to do so it uses sudo(8), while Err parazyd.org 70 i+pinentry(1) is adopted to collect passwords from the user. Tomb Err parazyd.org 70 i+executes as super user only when required. Err parazyd.org 70 i+ Err parazyd.org 70 i+To be made available on multi user systems, the superuser execution of Err parazyd.org 70 i+the tomb script can be authorized for users without jeopardizing the Err parazyd.org 70 i+whole system's security: just add such a line to \fI/etc/sudoers\fR: Err parazyd.org 70 i+ Err parazyd.org 70 i+.EX Err parazyd.org 70 i+ username ALL=NOPASSWD: /usr/local/bin/tomb Err parazyd.org 70 i+.EE Err parazyd.org 70 i+ Err parazyd.org 70 i+Password input is handled by the pinentry program: it can be text Err parazyd.org 70 i+based or graphical and is usually configured with a symlink. When Err parazyd.org 70 i+using Tomb in X11 it is better to use a graphical pinentry-gtk2 or Err parazyd.org 70 i+pinentry-qt because it helps preventing keylogging by other X Err parazyd.org 70 i+clients. When using it from a remote ssh connection it might be Err parazyd.org 70 i+necessary to force use of pinentry-curses for instance by unsetting Err parazyd.org 70 i+the DISPLAY environment var. Err parazyd.org 70 i+ Err parazyd.org 70 i+ Err parazyd.org 70 i+.SH SWAP Err parazyd.org 70 i+ Err parazyd.org 70 i+On execution of certain commands Tomb will complain about swap memory Err parazyd.org 70 i+on disk when present and \fIabort if your system has swap Err parazyd.org 70 i+activated\fR. You can disable this behaviour using the Err parazyd.org 70 i+\fI--force\fR. Before doing that, however, you may be interested in Err parazyd.org 70 i+knowing the risks of doing so: Err parazyd.org 70 i+.IP \(bu Err parazyd.org 70 i+During such operations a lack of available memory could cause the swap Err parazyd.org 70 i+to write your secret key on the disk. Err parazyd.org 70 i+.IP \(bu Err parazyd.org 70 i+Even while using an opened tomb, another application could occupy too Err parazyd.org 70 i+much memory so that the swap needs to be used, this way it is possible Err parazyd.org 70 i+that some contents of files contained into the tomb are physically Err parazyd.org 70 i+written on your disk, not encrypted. Err parazyd.org 70 i+.P Err parazyd.org 70 i+ Err parazyd.org 70 i+If you don't need swap, execute \fI swapoff -a\fR. If you really need Err parazyd.org 70 i+it, you could make an encrypted swap partition. Tomb doesn't detect if Err parazyd.org 70 i+your swap is encrypted, and will complain anyway. Err parazyd.org 70 i+ Err parazyd.org 70 i+.SH EXAMPLES Err parazyd.org 70 i+ Err parazyd.org 70 i+.IP \(bu Err parazyd.org 70 i+Create a 128MB large "secret" tomb and its keys, then open it: Err parazyd.org 70 i+ Err parazyd.org 70 i+.EX Err parazyd.org 70 i+ tomb dig -s 128 secret.tomb Err parazyd.org 70 i+ Err parazyd.org 70 i+ tomb forge secret.tomb.key Err parazyd.org 70 i+ Err parazyd.org 70 i+ tomb lock secret.tomb -k secret.tomb.key Err parazyd.org 70 i+ Err parazyd.org 70 i+ tomb open secret.tomb -k secret.tomb.key Err parazyd.org 70 i+.EE Err parazyd.org 70 i+ Err parazyd.org 70 i+.IP \(bu Err parazyd.org 70 i+Open a Tomb using the key from a remote SSH shell, without saving any Err parazyd.org 70 i+local copy of it: Err parazyd.org 70 i+ Err parazyd.org 70 i+.EX Err parazyd.org 70 i+ ssh user@my.shell.net 'cat .secrets/tomb.key' | tomb open secret.tomb -k - Err parazyd.org 70 i+.EE Err parazyd.org 70 i+ Err parazyd.org 70 i+.IP \(bu Err parazyd.org 70 i+Open a Tomb on a remote server passing the unencrypted local key on stdin via SSH, Err parazyd.org 70 i+without saving any remote copy of it: Err parazyd.org 70 i+ Err parazyd.org 70 i+.EX Err parazyd.org 70 i+ gpg -d .secrets/tomb.key | ssh server tomb open secret.tomb -k cleartext --unsafe Err parazyd.org 70 i+.EE Err parazyd.org 70 i+ Err parazyd.org 70 i+.IP \(bu Err parazyd.org 70 i+Create a bind hook that places your GnuPG folder inside the tomb, but Err parazyd.org 70 i+makes it reachable from the standard $HOME/.gnupg location every time Err parazyd.org 70 i+the tomb will be opened: Err parazyd.org 70 i+ Err parazyd.org 70 i+.EX Err parazyd.org 70 i+ tomb open GPG.tomb -k GPG.tomb.key Err parazyd.org 70 i+ echo ".gnupg .gnupg" > /media/GPG.tomb/bind-hooks Err parazyd.org 70 i+ mv ~/.gnupg /media/GPG.tomb/.gnupg && mkdir ~/.gnupg Err parazyd.org 70 i+ tomb close GPG && tomb open GPG.tomb -k GPG.tomb.key Err parazyd.org 70 i+.EE Err parazyd.org 70 i+ Err parazyd.org 70 i+.IP \(bu Err parazyd.org 70 i+Script a tomb to launch the Firefox browser every time is opened, Err parazyd.org 70 i+keeping all its profile data inside it: Err parazyd.org 70 i+ Err parazyd.org 70 i+.EX Err parazyd.org 70 i+ tomb open FOX.tomb -k FOX.tomb.key Err parazyd.org 70 i+ cat < /media/FOX.tomb/post-hooks Err parazyd.org 70 i+#!/bin/sh Err parazyd.org 70 i+if [ "$1" = "open" ]; then Err parazyd.org 70 i+ firefox -no-remote -profile "$2"/firefox-pro & Err parazyd.org 70 i+fi Err parazyd.org 70 i+EOF Err parazyd.org 70 i+ chmod +x /media/FOX.tomb/post-hooks Err parazyd.org 70 i+.EE Err parazyd.org 70 i+ Err parazyd.org 70 i+.IP \(bu Err parazyd.org 70 i+Script a tomb to archive Pictures using Shotwell, launching it on open: Err parazyd.org 70 i+ Err parazyd.org 70 i+.EX Err parazyd.org 70 i+ tomb open Pictures.tomb -k Pictures.tomb.key Err parazyd.org 70 i+ cat < /media/Pictures.tomb/bind-hooks Err parazyd.org 70 i+Pictures Pictures Err parazyd.org 70 i+EOF Err parazyd.org 70 i+ cat < /media/Pictures.tomb/post-hooks Err parazyd.org 70 i+#!/bin/sh Err parazyd.org 70 i+if [ "$1" = "open" ]; then Err parazyd.org 70 i+ which shotwell > /dev/null Err parazyd.org 70 i+ if [ "$?" = "0" ]; then Err parazyd.org 70 i+ shotwell -d "$2"/Pictures/.shotwell & Err parazyd.org 70 i+ fi Err parazyd.org 70 i+fi Err parazyd.org 70 i+EOF Err parazyd.org 70 i+ chmod +x /media/Pictures.tomb/post-hooks Err parazyd.org 70 i+.EE Err parazyd.org 70 i+ Err parazyd.org 70 i+.SH BUGS Err parazyd.org 70 i+Please report bugs on the Github issue tracker at Err parazyd.org 70 i+.UR https://github.com/dyne/Tomb/issues Err parazyd.org 70 i+.UE Err parazyd.org 70 i+ Err parazyd.org 70 i+One can also try to get in touch with developers via the #dyne chat channel on \fIhttps://irc.dyne.org\fR. Err parazyd.org 70 i+ Err parazyd.org 70 i+.SH AUTHORS Err parazyd.org 70 i+ Err parazyd.org 70 i+Tomb is designed, written and maintained by Denis Roio aka Jaromil. Err parazyd.org 70 i+ Err parazyd.org 70 i+Tomb includes code by Anathema, Boyska, Hellekin O. Wolf and GDrooid. Err parazyd.org 70 i+ Err parazyd.org 70 i+Tomb's artwork is contributed by Jordi aka Mon Mort and Logan VanCuren. Err parazyd.org 70 i+ Err parazyd.org 70 i+Gettext internationalization and Spanish translation is contributed by Err parazyd.org 70 i+GDrooid, French translation by Hellekin, Russian translation by fsLeg, Err parazyd.org 70 i+German translation by x3nu. Err parazyd.org 70 i+ Err parazyd.org 70 i+Testing, reviews and documentation are contributed by Dreamer, Shining Err parazyd.org 70 i+the Translucent, Mancausoft, Asbesto Molesto, Nignux, Vlax, The Grugq, Err parazyd.org 70 i+Reiven, GDrooid, Alphazo, Brian May, TheJH, fsLeg, JoelMon and the Err parazyd.org 70 i+Linux Action Show! Err parazyd.org 70 i+ Err parazyd.org 70 i+Cryptsetup was developed by Christophe Saout and Clemens Fruhwirth. Err parazyd.org 70 i+ Err parazyd.org 70 i+.SH COPYING Err parazyd.org 70 i+ Err parazyd.org 70 i+This manual is Copyright (c) 2011-2015 by Denis Roio <\fIjaromil@dyne.org\fR> Err parazyd.org 70 i+ Err parazyd.org 70 i+This manual includes contributions by Boyska and Hellekin O. Wolf. Err parazyd.org 70 i+ Err parazyd.org 70 i+Permission is granted to copy, distribute and/or modify this manual Err parazyd.org 70 i+under the terms of the GNU Free Documentation License, Version 1.1 or Err parazyd.org 70 i+any later version published by the Free Software Foundation. Err parazyd.org 70 i+Permission is granted to make and distribute verbatim copies of this Err parazyd.org 70 i+manual page provided the above copyright notice and this permission Err parazyd.org 70 i+notice are preserved on all copies. Err parazyd.org 70 i+ Err parazyd.org 70 i+.SH AVAILABILITY Err parazyd.org 70 i+ Err parazyd.org 70 i+The most recent version of Tomb sourcecode and up to date Err parazyd.org 70 i+documentation is available for download from its website on Err parazyd.org 70 i+\fIhttps://tomb.dyne.org\fR. Err parazyd.org 70 i+ Err parazyd.org 70 i+.SH SEE ALSO Err parazyd.org 70 i+ Err parazyd.org 70 i+.B Err parazyd.org 70 i+.IP cryptsetup(8) Err parazyd.org 70 i+ Err parazyd.org 70 i+GnuPG website: Err parazyd.org 70 i+.br Err parazyd.org 70 i+https://www.gnupg.org Err parazyd.org 70 i+ Err parazyd.org 70 i+DM-Crypt website: Err parazyd.org 70 i+.br Err parazyd.org 70 i+https://gitlab.com/cryptsetup/cryptsetup/wikis/DMCrypt Err parazyd.org 70 i+ Err parazyd.org 70 i+LUKS website: Err parazyd.org 70 i+.br Err parazyd.org 70 i+https://gitlab.com/cryptsetup/cryptsetup/wikis/home Err parazyd.org 70 1diff --git a/src/tomb/kdf-keys/.gitignore b/src/tomb/kdf-keys/.gitignore /git/coffin/file/src/tomb/kdf-keys/.gitignore.gph parazyd.org 70 it@@ -0,0 +1,4 @@ Err parazyd.org 70 i+tomb-kdf-pbkdf2 Err parazyd.org 70 i+tomb-kdf-pbkdf2-gensalt Err parazyd.org 70 i+tomb-kdf-pbkdf2-getiter Err parazyd.org 70 i+tomb-utils-hexencode Err parazyd.org 70 1diff --git a/src/tomb/kdf-keys/Makefile b/src/tomb/kdf-keys/Makefile /git/coffin/file/src/tomb/kdf-keys/Makefile.gph parazyd.org 70 it@@ -0,0 +1,18 @@ Err parazyd.org 70 i+ Err parazyd.org 70 i+PREFIX ?= /usr/local Err parazyd.org 70 i+ Err parazyd.org 70 i+all: Err parazyd.org 70 i+ $(CC) -O2 -o tomb-kdb-pbkdf2 pbkdf2.c -lgcrypt Err parazyd.org 70 i+ $(CC) -O2 -o tomb-kdb-pbkdf2-getiter benchmark.c -lgcrypt Err parazyd.org 70 i+ $(CC) -O2 -o tomb-kdb-pbkdf2-gensalt gen_salt.c -lgcrypt Err parazyd.org 70 i+ $(CC) -O2 -o tomb-kdb-hexencode hexencode.c Err parazyd.org 70 i+ Err parazyd.org 70 i+clean: Err parazyd.org 70 i+ rm -f tomb-kdb-pbkdf2 tomb-kdb-pbkdf2-getiter tomb-kdb-pbkdf2-gensalt tomb-kdb-hexencode Err parazyd.org 70 i+ Err parazyd.org 70 i+install: Err parazyd.org 70 i+ install -Dm755 tomb-kdb-pbkdf2 ${DESTDIR}${PREFIX}/bin/tomb-kdb-pbkdf2 Err parazyd.org 70 i+ install -Dm755 tomb-kdb-pbkdf2-getiter ${DESTDIR}${PREFIX}/bin/tomb-kdb-pbkdf2-getiter Err parazyd.org 70 i+ install -Dm755 tomb-kdb-pbkdf2-gensalt ${DESTDIR}${PREFIX}/bin/tomb-kdb-pbkdf2-gensalt Err parazyd.org 70 i+ install -Dm755 tomb-kdb-hexencode ${DESTDIR}${PREFIX}/bin/tomb-kdb-hexencode Err parazyd.org 70 i+ @echo "Tomb-kdb auxiliary binaries installed in ${DESTDIR}${PREFIX}/bin" Err parazyd.org 70 1diff --git a/src/tomb/kdf-keys/README b/src/tomb/kdf-keys/README /git/coffin/file/src/tomb/kdf-keys/README.gph parazyd.org 70 it@@ -0,0 +1,27 @@ Err parazyd.org 70 i+ Err parazyd.org 70 i+BUILD Err parazyd.org 70 i+------ Err parazyd.org 70 i+ Err parazyd.org 70 i+Just type make. Err parazyd.org 70 i+You need a recent development version of libgcrypt installed. Err parazyd.org 70 i+On Debian 7 (not earlier) the libgcrypt11-dev package works: Err parazyd.org 70 i+ # apt-get install libgcrypt11-dev Err parazyd.org 70 i+ Err parazyd.org 70 i+PLANS Err parazyd.org 70 i+------ Err parazyd.org 70 i+ Err parazyd.org 70 i+While this can be useful for general purpose, it specially fits tomb, and it's designed for easy integration and compilation. Err parazyd.org 70 i+ Err parazyd.org 70 i+Binary name will then be: Err parazyd.org 70 i+tomb-kdb-${algo} Err parazyd.org 70 i+tomb-kdb-${algo}-gensalt Err parazyd.org 70 i+tomb-kdb-${algo}-getiter Err parazyd.org 70 i+tomb-kdb-hexencode Err parazyd.org 70 i+ Err parazyd.org 70 i+Base64 vs hexencode Err parazyd.org 70 i+------------------- Err parazyd.org 70 i+ Err parazyd.org 70 i+While base64 is easier to use (shell command, more compact), pbkdf2 use hex Err parazyd.org 70 i+in its specifications. Err parazyd.org 70 i+This could be solved with an option (-x for hex, defaults to base64) Err parazyd.org 70 i+ Err parazyd.org 70 1diff --git a/src/tomb/kdf-keys/benchmark.c b/src/tomb/kdf-keys/benchmark.c /git/coffin/file/src/tomb/kdf-keys/benchmark.c.gph parazyd.org 70 it@@ -0,0 +1,59 @@ Err parazyd.org 70 i+#include Err parazyd.org 70 i+#include Err parazyd.org 70 i+#include Err parazyd.org 70 i+ Err parazyd.org 70 i+#include Err parazyd.org 70 i+ Err parazyd.org 70 i+#include Err parazyd.org 70 i+ Err parazyd.org 70 i+static long bench(int ic) { Err parazyd.org 70 i+ char *pass = "mypass"; Err parazyd.org 70 i+ unsigned char *salt = "abcdefghijklmno"; Err parazyd.org 70 i+ int salt_len = strlen(salt); Err parazyd.org 70 i+ int result_len = 64; Err parazyd.org 70 i+ unsigned char *result = calloc(result_len, sizeof(char)); Err parazyd.org 70 i+ struct timeval start, end; Err parazyd.org 70 i+ long microtime; Err parazyd.org 70 i+ Err parazyd.org 70 i+ gettimeofday(&start, NULL); Err parazyd.org 70 i+ gcry_kdf_derive( pass, strlen(pass), GCRY_KDF_PBKDF2, GCRY_MD_SHA1, salt, salt_len, ic, result_len, result); Err parazyd.org 70 i+ gettimeofday(&end, NULL); Err parazyd.org 70 i+ microtime = 1000000*end.tv_sec+end.tv_usec - (1000000*start.tv_sec+start.tv_usec); Err parazyd.org 70 i+ Err parazyd.org 70 i+ return (long)microtime; Err parazyd.org 70 i+} Err parazyd.org 70 i+int main(int argc, char *argv[]) Err parazyd.org 70 i+{ Err parazyd.org 70 i+ long desired_time = 1000000; Err parazyd.org 70 i+ long microtime; Err parazyd.org 70 i+ int ic=100; Err parazyd.org 70 i+ int tries=0; Err parazyd.org 70 i+ if(argc >= 2) Err parazyd.org 70 i+ sscanf(argv[1], "%ld", &desired_time); Err parazyd.org 70 i+ if (!gcry_check_version ("1.5.0")) { Err parazyd.org 70 i+ fputs ("libgcrypt version mismatch\n", stderr); Err parazyd.org 70 i+ exit (2); Err parazyd.org 70 i+ } Err parazyd.org 70 i+ /* Allocate a pool of 16k secure memory. This make the secure memory Err parazyd.org 70 i+ available and also drops privileges where needed. */ Err parazyd.org 70 i+ gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0); Err parazyd.org 70 i+ /* It is now okay to let Libgcrypt complain when there was/is Err parazyd.org 70 i+ a problem with the secure memory. */ Err parazyd.org 70 i+ gcry_control (GCRYCTL_RESUME_SECMEM_WARN); Err parazyd.org 70 i+ /* Tell Libgcrypt that initialization has completed. */ Err parazyd.org 70 i+ gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0); Err parazyd.org 70 i+ Err parazyd.org 70 i+ Err parazyd.org 70 i+ microtime = bench(ic); Err parazyd.org 70 i+ while( abs(desired_time-microtime) > (desired_time/10) /*little difference */ Err parazyd.org 70 i+ && tries++ <= 5) { Err parazyd.org 70 i+ float ratio = (float)desired_time/microtime; Err parazyd.org 70 i+ if(ratio > 1000) ratio=1000.0; Err parazyd.org 70 i+ ic*=ratio; Err parazyd.org 70 i+ if(ic<1) ic=1; Err parazyd.org 70 i+ microtime = bench(ic); Err parazyd.org 70 i+ } Err parazyd.org 70 i+ printf("%d\n", ic); Err parazyd.org 70 i+ return 0; Err parazyd.org 70 i+ Err parazyd.org 70 i+} Err parazyd.org 70 1diff --git a/src/tomb/kdf-keys/gen_salt.c b/src/tomb/kdf-keys/gen_salt.c /git/coffin/file/src/tomb/kdf-keys/gen_salt.c.gph parazyd.org 70 it@@ -0,0 +1,39 @@ Err parazyd.org 70 i+#include Err parazyd.org 70 i+#include Err parazyd.org 70 i+#include Err parazyd.org 70 i+ Err parazyd.org 70 i+void print_hex(unsigned char *buf, int len) Err parazyd.org 70 i+{ Err parazyd.org 70 i+ int i; Err parazyd.org 70 i+ Err parazyd.org 70 i+ for(i=0;i=2) { Err parazyd.org 70 i+ if(sscanf(argv[1], "%d", &len) != 1) { Err parazyd.org 70 i+ fprintf(stderr, "Error: len must be an integer\n"); Err parazyd.org 70 i+ return 1; Err parazyd.org 70 i+ } Err parazyd.org 70 i+ } Err parazyd.org 70 i+ buf = calloc(len, sizeof(char)); Err parazyd.org 70 i+ memset(buf, 9, len); Err parazyd.org 70 i+ rand = fopen("/dev/random", "r"); Err parazyd.org 70 i+ res = fread(buf, sizeof(char), len, rand); Err parazyd.org 70 i+ if( res != len) { Err parazyd.org 70 i+ fprintf(stderr, "Error reading /dev/random: %d != %d, \n", res, len); Err parazyd.org 70 i+ fclose(rand); Err parazyd.org 70 i+ free(buf); Err parazyd.org 70 i+ return 2; Err parazyd.org 70 i+ } Err parazyd.org 70 i+ fclose(rand); Err parazyd.org 70 i+ print_hex(buf, len); Err parazyd.org 70 i+ free(buf); Err parazyd.org 70 i+ return 0; Err parazyd.org 70 i+} Err parazyd.org 70 1diff --git a/src/tomb/kdf-keys/hexencode.c b/src/tomb/kdf-keys/hexencode.c /git/coffin/file/src/tomb/kdf-keys/hexencode.c.gph parazyd.org 70 it@@ -0,0 +1,49 @@ Err parazyd.org 70 i+/* Err parazyd.org 70 i+ * A simple utility that reads from stdin and output the hexencoding (on a single line) of the input Err parazyd.org 70 i+ */ Err parazyd.org 70 i+ Err parazyd.org 70 i+#include Err parazyd.org 70 i+#include Err parazyd.org 70 i+#include Err parazyd.org 70 i+ Err parazyd.org 70 i+static int decode_mode = 0; Err parazyd.org 70 i+int main(int argc, char *argv[]) { Err parazyd.org 70 i+ char c; Err parazyd.org 70 i+ char buf[3]; Err parazyd.org 70 i+ int read_bytes; Err parazyd.org 70 i+ int opt; Err parazyd.org 70 i+ static struct option long_options[] = Err parazyd.org 70 i+ { Err parazyd.org 70 i+ {"decode", no_argument, &decode_mode, 1}, Err parazyd.org 70 i+ {"encode", no_argument, &decode_mode, 0}, Err parazyd.org 70 i+ {0,0,0,0} Err parazyd.org 70 i+ }; Err parazyd.org 70 i+ int option_index = 0; Err parazyd.org 70 i+ Err parazyd.org 70 i+ while(1) { Err parazyd.org 70 i+ option_index = 0; Err parazyd.org 70 i+ opt = getopt_long(argc, argv, "", long_options, &option_index); Err parazyd.org 70 i+ if(opt == -1) Err parazyd.org 70 i+ break; Err parazyd.org 70 i+ switch(opt) { Err parazyd.org 70 i+ case 0: Err parazyd.org 70 i+ break; Err parazyd.org 70 i+ case '?': Err parazyd.org 70 i+ return 127; Err parazyd.org 70 i+ default: Err parazyd.org 70 i+ abort(); Err parazyd.org 70 i+ } Err parazyd.org 70 i+ } Err parazyd.org 70 i+ if(decode_mode == 0) { Err parazyd.org 70 i+ while(( c = (char)getchar() ) != EOF) Err parazyd.org 70 i+ printf("%02x", c); Err parazyd.org 70 i+ return 0; Err parazyd.org 70 i+ } else { Err parazyd.org 70 i+ while( (read_bytes=fread(buf, sizeof(char), 2, stdin)) != 0) { Err parazyd.org 70 i+ if(read_bytes == 1) buf[1]='\0'; Err parazyd.org 70 i+ sscanf(buf, "%x", &c); Err parazyd.org 70 i+ printf("%c", c); Err parazyd.org 70 i+ } Err parazyd.org 70 i+ return 0; Err parazyd.org 70 i+ } Err parazyd.org 70 i+} Err parazyd.org 70 1diff --git a/src/tomb/kdf-keys/pbkdf2.c b/src/tomb/kdf-keys/pbkdf2.c /git/coffin/file/src/tomb/kdf-keys/pbkdf2.c.gph parazyd.org 70 it@@ -0,0 +1,144 @@ Err parazyd.org 70 i+/* Err parazyd.org 70 i+** SYNOPSIS Err parazyd.org 70 i+** echo "passphrase" | pbkdf2 salt_hex count > 48_byte_hex_key_and_iv Err parazyd.org 70 i+** Err parazyd.org 70 i+** DESCRIPTION Err parazyd.org 70 i+** Err parazyd.org 70 i+** Make the "Password-Based Key Derivation Function v2" function found in Err parazyd.org 70 i+** the openssl library available to the command line, as it is not available Err parazyd.org 70 i+** for use from the "openssl" command. At the time of writing the "openssl" Err parazyd.org 70 i+** command only encrypts using the older, 'fast' pbkdf1.5 method. Err parazyd.org 70 i+** Err parazyd.org 70 i+** The 'salt_hex' is the salt to be used, as a hexadecimal string. Typically Err parazyd.org 70 i+** this is 8 bytes (64 bit), and is an assigned randomly during encryption. Err parazyd.org 70 i+** Err parazyd.org 70 i+** The 'count' is iteration count used to make the calculation of the key Err parazyd.org 70 i+** from the passphrase longer so as to take 1/2 to 2 seconds to generate. Err parazyd.org 70 i+** This complexity prevents slows down brute force attacks enormously. Err parazyd.org 70 i+** Err parazyd.org 70 i+** The output of the above is a 48 bytes in hexadeximal, which is typically Err parazyd.org 70 i+** used for 32 byte encryption key KEY and a 16 byte IV as needed by Err parazyd.org 70 i+** Crypt-AES-256 (or some other encryption method). Err parazyd.org 70 i+** Err parazyd.org 70 i+** NOTE: While the "openssl" command can accept a hex encoded 'key' and 'iv' Err parazyd.org 70 i+** it only does so on the command line, which is insecure. As such I Err parazyd.org 70 i+** recommend that the output only be used with API access to the "OpenSSL" Err parazyd.org 70 i+** cryptography libraries. Err parazyd.org 70 i+** Err parazyd.org 70 i+************* Err parazyd.org 70 i+** Err parazyd.org 70 i+** Anthony Thyssen 4 November 2009 A.Thyssen@griffith.edu.au Err parazyd.org 70 i+** Err parazyd.org 70 i+** Based on a test program "pkcs5.c" found on Err parazyd.org 70 i+** http://www.mail-archive.com/openssl-users@openssl.org Err parazyd.org 70 i+** which uses openssl to perform PBKDF2 (RFC2898) iteritive (slow) password Err parazyd.org 70 i+** hashing. Err parazyd.org 70 i+** Err parazyd.org 70 i+** Build Err parazyd.org 70 i+** gcc -o pbkdf2 pbkdf2.c -lcrypto Err parazyd.org 70 i+** Err parazyd.org 70 i+*/ Err parazyd.org 70 i+#include Err parazyd.org 70 i+#include Err parazyd.org 70 i+ Err parazyd.org 70 i+#include Err parazyd.org 70 i+ Err parazyd.org 70 i+/* TODO: move print_hex and hex_to_binary to utils.h, with separate compiling */ Err parazyd.org 70 i+void print_hex(unsigned char *buf, int len) Err parazyd.org 70 i+{ Err parazyd.org 70 i+ int i; Err parazyd.org 70 i+ Err parazyd.org 70 i+ for(i=0;ibinary_key_iv\n", argv[0]); Err parazyd.org 70 i+ exit(10); Err parazyd.org 70 i+ } Err parazyd.org 70 i+ Err parazyd.org 70 i+ //TODO: move to base64decode Err parazyd.org 70 i+ salt=calloc(strlen(argv[1])/2+3, sizeof(char)); Err parazyd.org 70 i+ salt_len=hex_to_binary(salt, argv[1]); Err parazyd.org 70 i+ if( salt_len <= 0 ) { Err parazyd.org 70 i+ fprintf(stderr, "Error: %s is not a valid salt (it must be a hexadecimal string)\n", argv[1]); Err parazyd.org 70 i+ exit(1); Err parazyd.org 70 i+ } Err parazyd.org 70 i+ Err parazyd.org 70 i+ if( sscanf(argv[2], "%d", &ic) == 0 || ic<=0) { Err parazyd.org 70 i+ fprintf(stderr, "Error: count must be a positive integer\n"); Err parazyd.org 70 i+ exit(1); Err parazyd.org 70 i+ } Err parazyd.org 70 i+ if( sscanf(argv[3], "%d", &result_len) == 0 || result_len<=0) { Err parazyd.org 70 i+ fprintf(stderr, "Error: result_len must be a positive integer\n"); Err parazyd.org 70 i+ exit(1); Err parazyd.org 70 i+ } Err parazyd.org 70 i+ Err parazyd.org 70 i+ fscanf(stdin, "%ms", &pass); Err parazyd.org 70 i+ if ( pass[strlen(pass)-1] == '\n' ) Err parazyd.org 70 i+ pass[strlen(pass)-1] = '\0'; Err parazyd.org 70 i+ Err parazyd.org 70 i+ // PBKDF 2 Err parazyd.org 70 i+ result = calloc(result_len, sizeof(unsigned char*)); Err parazyd.org 70 i+ if (!gcry_check_version ("1.5.0")) { Err parazyd.org 70 i+ fputs ("libgcrypt version mismatch\n", stderr); Err parazyd.org 70 i+ exit (2); Err parazyd.org 70 i+ } Err parazyd.org 70 i+ /* Allocate a pool of 16k secure memory. This make the secure memory Err parazyd.org 70 i+ available and also drops privileges where needed. */ Err parazyd.org 70 i+ gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0); Err parazyd.org 70 i+ /* It is now okay to let Libgcrypt complain when there was/is Err parazyd.org 70 i+ a problem with the secure memory. */ Err parazyd.org 70 i+ gcry_control (GCRYCTL_RESUME_SECMEM_WARN); Err parazyd.org 70 i+ /* Tell Libgcrypt that initialization has completed. */ Err parazyd.org 70 i+ gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0); Err parazyd.org 70 i+ Err parazyd.org 70 i+ gcry_kdf_derive( pass, strlen(pass), GCRY_KDF_PBKDF2, GCRY_MD_SHA1, salt, salt_len, ic, result_len, result); Err parazyd.org 70 i+ print_hex(result, result_len); // Key + IV (as hex string) Err parazyd.org 70 i+ Err parazyd.org 70 i+ //clear and free everything Err parazyd.org 70 i+ for(i=0; i&2 Err parazyd.org 70 i+ error=$((error + 1)) Err parazyd.org 70 i+ fi Err parazyd.org 70 i+done < test.txt Err parazyd.org 70 i+ Err parazyd.org 70 i+if [[ $error == 1 ]]; then Err parazyd.org 70 i+ exit $error Err parazyd.org 70 i+fi Err parazyd.org 70 1diff --git a/src/tomb/kdf-keys/test.txt b/src/tomb/kdf-keys/test.txt /git/coffin/file/src/tomb/kdf-keys/test.txt.gph parazyd.org 70 iBinary files differ. Err parazyd.org 70 1diff --git a/src/tomb/tomb b/src/tomb/tomb /git/coffin/file/src/tomb/tomb.gph parazyd.org 70 it@@ -0,0 +1,2834 @@ Err parazyd.org 70 i+#!/bin/zsh Err parazyd.org 70 i+# Err parazyd.org 70 i+# Tomb, the Crypto Undertaker Err parazyd.org 70 i+# Err parazyd.org 70 i+# A commandline tool to easily operate encryption of secret data Err parazyd.org 70 i+# Err parazyd.org 70 i+ Err parazyd.org 70 i+# {{{ License Err parazyd.org 70 i+ Err parazyd.org 70 i+# Copyright (C) 2007-2016 Dyne.org Foundation Err parazyd.org 70 i+# Err parazyd.org 70 i+# Tomb is designed, written and maintained by Denis Roio Err parazyd.org 70 i+# Err parazyd.org 70 i+# With contributions by Anathema, Boyska, Hellekin O. Wolf and GDrooid Err parazyd.org 70 i+# Err parazyd.org 70 i+# Gettext internationalization and Spanish translation is contributed by Err parazyd.org 70 i+# GDrooid, French translation by Hellekin, Russian translation by fsLeg, Err parazyd.org 70 i+# German translation by x3nu. Err parazyd.org 70 i+# Err parazyd.org 70 i+# Testing, reviews and documentation are contributed by Dreamer, Shining Err parazyd.org 70 i+# the Translucent, Mancausoft, Asbesto Molesto, Nignux, Vlax, The Grugq, Err parazyd.org 70 i+# Reiven, GDrooid, Alphazo, Brian May, TheJH, fsLeg, JoelMon and the Err parazyd.org 70 i+# Linux Action Show! Err parazyd.org 70 i+# Err parazyd.org 70 i+# Tomb's artwork is contributed by Jordi aka Mon Mort and Logan VanCuren. Err parazyd.org 70 i+# Err parazyd.org 70 i+# Cryptsetup was developed by Christophe Saout and Clemens Fruhwirth. Err parazyd.org 70 i+ Err parazyd.org 70 i+# This source code is free software; you can redistribute it and/or Err parazyd.org 70 i+# modify it under the terms of the GNU Public License as published by Err parazyd.org 70 i+# the Free Software Foundation; either version 3 of the License, or Err parazyd.org 70 i+# (at your option) any later version. Err parazyd.org 70 i+# Err parazyd.org 70 i+# This source code is distributed in the hope that it will be useful, Err parazyd.org 70 i+# but WITHOUT ANY WARRANTY; without even the implied warranty of Err parazyd.org 70 i+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Please refer Err parazyd.org 70 i+# to the GNU Public License for more details. Err parazyd.org 70 i+# Err parazyd.org 70 i+# You should have received a copy of the GNU Public License along with Err parazyd.org 70 i+# this source code; if not, write to: Free Software Foundation, Inc., Err parazyd.org 70 i+# 675 Mass Ave, Cambridge, MA 02139, USA. Err parazyd.org 70 i+ Err parazyd.org 70 i+# }}} - License Err parazyd.org 70 i+ Err parazyd.org 70 i+# {{{ Global variables Err parazyd.org 70 i+ Err parazyd.org 70 i+typeset VERSION="2.2" Err parazyd.org 70 i+typeset DATE="Dec/2015" Err parazyd.org 70 i+typeset TOMBEXEC=$0 Err parazyd.org 70 i+typeset TMPPREFIX=${TMPPREFIX:-/tmp} Err parazyd.org 70 i+# TODO: configure which tmp dir to use from a cli flag Err parazyd.org 70 i+ Err parazyd.org 70 i+# Tomb is using some global variables set by the shell: Err parazyd.org 70 i+# TMPPREFIX, UID, GID, PATH, TTY, USERNAME Err parazyd.org 70 i+# You can grep 'global variable' to see where they are used. Err parazyd.org 70 i+ Err parazyd.org 70 i+# Keep a reference of the original command line arguments Err parazyd.org 70 i+typeset -a OLDARGS Err parazyd.org 70 i+for arg in "${(@)argv}"; do OLDARGS+=("$arg"); done Err parazyd.org 70 i+ Err parazyd.org 70 i+# Special command requirements Err parazyd.org 70 i+typeset -a DD WIPE PINENTRY Err parazyd.org 70 i+DD=(dd) Err parazyd.org 70 i+WIPE=(rm -f) Err parazyd.org 70 i+PINENTRY=(pinentry) Err parazyd.org 70 i+ Err parazyd.org 70 i+# load zsh regex module Err parazyd.org 70 i+zmodload zsh/regex Err parazyd.org 70 i+zmodload zsh/mapfile Err parazyd.org 70 i+zmodload -F zsh/stat b:zstat Err parazyd.org 70 i+ Err parazyd.org 70 i+# make sure variables aren't exported Err parazyd.org 70 i+unsetopt allexport Err parazyd.org 70 i+ Err parazyd.org 70 i+# Flag optional commands if available (see _ensure_dependencies()) Err parazyd.org 70 i+typeset -i KDF=1 Err parazyd.org 70 i+typeset -i STEGHIDE=1 Err parazyd.org 70 i+typeset -i RESIZER=1 Err parazyd.org 70 i+typeset -i SWISH=1 Err parazyd.org 70 i+typeset -i QRENCODE=1 Err parazyd.org 70 i+ Err parazyd.org 70 i+# Default mount options Err parazyd.org 70 i+typeset MOUNTOPTS="rw,noatime,nodev" Err parazyd.org 70 i+ Err parazyd.org 70 i+# Makes glob matching case insensitive Err parazyd.org 70 i+unsetopt CASE_MATCH Err parazyd.org 70 i+ Err parazyd.org 70 i+typeset -AH OPTS # Command line options (see main()) Err parazyd.org 70 i+ Err parazyd.org 70 i+# Command context (see _whoami()) Err parazyd.org 70 i+typeset -H _USER # Running username Err parazyd.org 70 i+typeset -Hi _UID # Running user identifier Err parazyd.org 70 i+typeset -Hi _GID # Running user group identifier Err parazyd.org 70 i+typeset -H _TTY # Connected input terminal Err parazyd.org 70 i+ Err parazyd.org 70 i+# Tomb context (see _plot()) Err parazyd.org 70 i+typeset -H TOMBPATH # Full path to the tomb Err parazyd.org 70 i+typeset -H TOMBDIR # Directory where the tomb is Err parazyd.org 70 i+typeset -H TOMBFILE # File name of the tomb Err parazyd.org 70 i+typeset -H TOMBNAME # Name of the tomb Err parazyd.org 70 i+ Err parazyd.org 70 i+# Tomb secrets Err parazyd.org 70 i+typeset -H TOMBKEY # Encrypted key contents (see forge_key(), recover_key()) Err parazyd.org 70 i+typeset -H TOMBKEYFILE # Key file (ditto) Err parazyd.org 70 i+typeset -H TOMBSECRET # Raw deciphered key (see forge_key(), gpg_decrypt()) Err parazyd.org 70 i+typeset -H TOMBPASSWORD # Raw tomb passphrase (see gen_key(), ask_key_password()) Err parazyd.org 70 i+typeset -H TOMBTMP # Filename of secure temp just created (see _tmp_create()) Err parazyd.org 70 i+ Err parazyd.org 70 i+typeset -aH TOMBTMPFILES # Keep track of temporary files Err parazyd.org 70 i+typeset -aH TOMBLOOPDEVS # Keep track of used loop devices Err parazyd.org 70 i+ Err parazyd.org 70 i+# Make sure sbin is in PATH (man zshparam) Err parazyd.org 70 i+path+=( /sbin /usr/sbin ) Err parazyd.org 70 i+ Err parazyd.org 70 i+# For gettext Err parazyd.org 70 i+export TEXTDOMAIN=tomb Err parazyd.org 70 i+ Err parazyd.org 70 i+# }}} Err parazyd.org 70 i+ Err parazyd.org 70 i+# {{{ Safety functions Err parazyd.org 70 i+ Err parazyd.org 70 i+# Wrap sudo with a more visible message Err parazyd.org 70 i+_sudo() { Err parazyd.org 70 i+ local sudo_eng="[sudo] Enter password for user ::1 user:: to gain superuser privileges" Err parazyd.org 70 i+ local msg="$(gettext -s "$sudo_eng")" Err parazyd.org 70 i+ msg=${(S)msg//::1*::/$USER} Err parazyd.org 70 i+ sudo -p " Err parazyd.org 70 i+$msg Err parazyd.org 70 i+ Err parazyd.org 70 i+" ${@} Err parazyd.org 70 i+} Err parazyd.org 70 i+ Err parazyd.org 70 i+# Cleanup anything sensitive before exiting. Err parazyd.org 70 i+_endgame() { Err parazyd.org 70 i+ Err parazyd.org 70 i+ # Prepare some random material to overwrite vars Err parazyd.org 70 i+ local rr="$RANDOM" Err parazyd.org 70 i+ while [[ ${#rr} -lt 500 ]]; do Err parazyd.org 70 i+ rr+="$RANDOM" Err parazyd.org 70 i+ done Err parazyd.org 70 i+ Err parazyd.org 70 i+ # Ensure no information is left in unallocated memory Err parazyd.org 70 i+ TOMBPATH="$rr"; unset TOMBPATH Err parazyd.org 70 i+ TOMBDIR="$rr"; unset TOMBDIR Err parazyd.org 70 i+ TOMBFILE="$rr"; unset TOMBFILE Err parazyd.org 70 i+ TOMBNAME="$rr"; unset TOMBNAME Err parazyd.org 70 i+ TOMBKEY="$rr"; unset TOMBKEY Err parazyd.org 70 i+ TOMBKEYFILE="$rr"; unset TOMBKEYFILE Err parazyd.org 70 i+ TOMBSECRET="$rr"; unset TOMBSECRET Err parazyd.org 70 i+ TOMBPASSWORD="$rr"; unset TOMBPASSWORD Err parazyd.org 70 i+ Err parazyd.org 70 i+ # Clear temporary files Err parazyd.org 70 i+ for f in $TOMBTMPFILES; do Err parazyd.org 70 i+ ${=WIPE} "$f" Err parazyd.org 70 i+ done Err parazyd.org 70 i+ unset TOMBTMPFILES Err parazyd.org 70 i+ Err parazyd.org 70 i+ # Detach loop devices Err parazyd.org 70 i+ for l in $TOMBLOOPDEVS; do Err parazyd.org 70 i+ _sudo losetup -d "$l" Err parazyd.org 70 i+ done Err parazyd.org 70 i+ unset TOMBLOOPDEVS Err parazyd.org 70 i+ Err parazyd.org 70 i+} Err parazyd.org 70 i+ Err parazyd.org 70 i+# Trap functions for the _endgame event Err parazyd.org 70 i+TRAPINT() { _endgame INT } Err parazyd.org 70 i+TRAPEXIT() { _endgame EXIT } Err parazyd.org 70 i+TRAPHUP() { _endgame HUP } Err parazyd.org 70 i+TRAPQUIT() { _endgame QUIT } Err parazyd.org 70 i+TRAPABRT() { _endgame ABORT } Err parazyd.org 70 i+TRAPKILL() { _endgame KILL } Err parazyd.org 70 i+TRAPPIPE() { _endgame PIPE } Err parazyd.org 70 i+TRAPTERM() { _endgame TERM } Err parazyd.org 70 i+TRAPSTOP() { _endgame STOP } Err parazyd.org 70 i+ Err parazyd.org 70 i+_cat() { local -a _arr; Err parazyd.org 70 i+ # read file using mapfile, newline fix Err parazyd.org 70 i+ _arr=("${(f@)${mapfile[${1}]%$ā€™\nā€™}}"); print "$_arr" Err parazyd.org 70 i+} Err parazyd.org 70 i+ Err parazyd.org 70 i+_is_found() { Err parazyd.org 70 i+ # returns 0 if binary is found in path Err parazyd.org 70 i+ [[ "$1" = "" ]] && return 1 Err parazyd.org 70 i+ command -v "$1" 1>/dev/null 2>/dev/null Err parazyd.org 70 i+ return $? Err parazyd.org 70 i+} Err parazyd.org 70 i+ Err parazyd.org 70 i+# Identify the running user Err parazyd.org 70 i+# Set global variables _UID, _GID, _TTY, and _USER, either from the Err parazyd.org 70 i+# command line, -U, -G, -T, respectively, or from the environment. Err parazyd.org 70 i+# Also update USERNAME and HOME to maintain consistency. Err parazyd.org 70 i+_whoami() { Err parazyd.org 70 i+ Err parazyd.org 70 i+ # Set username from UID or environment Err parazyd.org 70 i+ _USER=$SUDO_USER Err parazyd.org 70 i+ [[ "$_USER" = "" ]] && { _USER=$USERNAME } Err parazyd.org 70 i+ [[ "$_USER" = "" ]] && { _USER=$(id -u) } Err parazyd.org 70 i+ [[ "$_USER" = "" ]] && { Err parazyd.org 70 i+ _failure "Failing to identify the user who is calling us" } Err parazyd.org 70 i+ Err parazyd.org 70 i+ # Get GID from option -G or the environment Err parazyd.org 70 i+ option_is_set -G \ Err parazyd.org 70 i+ && _GID=$(option_value -G) || _GID=$(id -g $_USER) Err parazyd.org 70 i+ Err parazyd.org 70 i+ # Get UID from option -U or the environment Err parazyd.org 70 i+ option_is_set -U \ Err parazyd.org 70 i+ && _UID=$(option_value -U) || _UID=$(id -u $_USER) Err parazyd.org 70 i+ Err parazyd.org 70 i+ _verbose "Identified caller: ::1 username:: (::2 UID:::::3 GID::)" $_USER $_UID $_GID Err parazyd.org 70 i+ Err parazyd.org 70 i+ # Update USERNAME accordingly if possible Err parazyd.org 70 i+ [[ $EUID == 0 && $_USER != $USERNAME ]] && { Err parazyd.org 70 i+ _verbose "Updating USERNAME from '::1 USERNAME::' to '::2 _USER::')" $USERNAME $_USER Err parazyd.org 70 i+ USERNAME=$_USER Err parazyd.org 70 i+ } Err parazyd.org 70 i+ Err parazyd.org 70 i+ # Force HOME to _USER's HOME if necessary Err parazyd.org 70 i+ local home=$(awk -F: "/^$_USER:/ { print \$6 }" /etc/passwd 2>/dev/null) Err parazyd.org 70 i+ [[ $home == $HOME ]] || { Err parazyd.org 70 i+ _verbose "Updating HOME to match user's: ::1 home:: (was ::2 HOME::)" \ Err parazyd.org 70 i+ $home $HOME Err parazyd.org 70 i+ HOME=$home } Err parazyd.org 70 i+ Err parazyd.org 70 i+ # Get connecting TTY from option -T or the environment Err parazyd.org 70 i+ option_is_set -T && _TTY=$(option_value -T) Err parazyd.org 70 i+ [[ -z $_TTY ]] && _TTY=$TTY Err parazyd.org 70 i+ Err parazyd.org 70 i+} Err parazyd.org 70 i+ Err parazyd.org 70 i+# Define sepulture's plot (setup tomb-related arguments) Err parazyd.org 70 i+# Synopsis: _plot /path/to/the.tomb Err parazyd.org 70 i+# Set TOMB{PATH,DIR,FILE,NAME} Err parazyd.org 70 i+_plot() { Err parazyd.org 70 i+ Err parazyd.org 70 i+ # We set global variables Err parazyd.org 70 i+ typeset -g TOMBPATH TOMBDIR TOMBFILE TOMBNAME Err parazyd.org 70 i+ Err parazyd.org 70 i+ TOMBPATH="$1" Err parazyd.org 70 i+ Err parazyd.org 70 i+ TOMBDIR=$(dirname $TOMBPATH) Err parazyd.org 70 i+ Err parazyd.org 70 i+ TOMBFILE=$(basename $TOMBPATH) Err parazyd.org 70 i+ Err parazyd.org 70 i+ # The tomb name is TOMBFILE without an extension. Err parazyd.org 70 i+ # It can start with dots: ..foo.tomb -> ..foo Err parazyd.org 70 i+ TOMBNAME="${TOMBFILE%\.[^\.]*}" Err parazyd.org 70 i+ [[ -z $TOMBNAME ]] && { Err parazyd.org 70 i+ _failure "Tomb won't work without a TOMBNAME." } Err parazyd.org 70 i+ Err parazyd.org 70 i+} Err parazyd.org 70 i+ Err parazyd.org 70 i+# Provide a random filename in shared memory Err parazyd.org 70 i+_tmp_create() { Err parazyd.org 70 i+ [[ -d "$TMPPREFIX" ]] || { Err parazyd.org 70 i+ # we create the tempdir with the sticky bit on Err parazyd.org 70 i+ _sudo mkdir -m 1777 "$TMPPREFIX" Err parazyd.org 70 i+ [[ $? == 0 ]] || _failure "Fatal error creating the temporary directory: ::1 temp dir::" "$TMPPREFIX" Err parazyd.org 70 i+ } Err parazyd.org 70 i+ Err parazyd.org 70 i+ # We're going to add one more $RANDOM for each time someone complains Err parazyd.org 70 i+ # about this being too weak of a random. Err parazyd.org 70 i+ tfile="${TMPPREFIX}/$RANDOM$RANDOM$RANDOM$RANDOM" # Temporary file Err parazyd.org 70 i+ umask 066 Err parazyd.org 70 i+ [[ $? == 0 ]] || { Err parazyd.org 70 i+ _failure "Fatal error setting the permission umask for temporary files" } Err parazyd.org 70 i+ Err parazyd.org 70 i+ [[ -r "$tfile" ]] && { Err parazyd.org 70 i+ _failure "Someone is messing up with us trying to hijack temporary files." } Err parazyd.org 70 i+ Err parazyd.org 70 i+ touch "$tfile" Err parazyd.org 70 i+ [[ $? == 0 ]] || { Err parazyd.org 70 i+ _failure "Fatal error creating a temporary file: ::1 temp file::" "$tfile" } Err parazyd.org 70 i+ Err parazyd.org 70 i+ _verbose "Created tempfile: ::1 temp file::" "$tfile" Err parazyd.org 70 i+ TOMBTMP="$tfile" Err parazyd.org 70 i+ TOMBTMPFILES+=("$tfile") Err parazyd.org 70 i+ Err parazyd.org 70 i+ return 0 Err parazyd.org 70 i+} Err parazyd.org 70 i+ Err parazyd.org 70 i+# Check if a *block* device is encrypted Err parazyd.org 70 i+# Synopsis: _is_encrypted_block /path/to/block/device Err parazyd.org 70 i+# Return 0 if it is an encrypted block device Err parazyd.org 70 i+_is_encrypted_block() { Err parazyd.org 70 i+ local b=$1 # Path to a block device Err parazyd.org 70 i+ local s="" # lsblk option -s (if available) Err parazyd.org 70 i+ Err parazyd.org 70 i+ # Issue #163 Err parazyd.org 70 i+ # lsblk --inverse appeared in util-linux 2.22 Err parazyd.org 70 i+ # but --version is not consistent... Err parazyd.org 70 i+ lsblk --help | grep -Fq -- --inverse Err parazyd.org 70 i+ [[ $? -eq 0 ]] && s="--inverse" Err parazyd.org 70 i+ Err parazyd.org 70 i+ sudo lsblk $s -o type -n $b 2>/dev/null \ Err parazyd.org 70 i+ | egrep -q '^crypt$' Err parazyd.org 70 i+ Err parazyd.org 70 i+ return $? Err parazyd.org 70 i+} Err parazyd.org 70 i+ Err parazyd.org 70 i+# Check if swap is activated Err parazyd.org 70 i+# Return 0 if NO swap is used, 1 if swap is used. Err parazyd.org 70 i+# Return 1 if any of the swaps is not encrypted. Err parazyd.org 70 i+# Return 2 if swap(s) is(are) used, but ALL encrypted. Err parazyd.org 70 i+# Use _check_swap in functions. It will call this function and Err parazyd.org 70 i+# exit if unsafe swap is present. Err parazyd.org 70 i+_ensure_safe_swap() { Err parazyd.org 70 i+ Err parazyd.org 70 i+ local -i r=1 # Return code: 0 no swap, 1 unsafe swap, 2 encrypted Err parazyd.org 70 i+ local -a swaps # List of swap partitions Err parazyd.org 70 i+ local bone is_crypt Err parazyd.org 70 i+ Err parazyd.org 70 i+ swaps="$(awk '/^\// { print $1 }' /proc/swaps 2>/dev/null)" Err parazyd.org 70 i+ [[ -z "$swaps" ]] && return 0 # No swap partition is active Err parazyd.org 70 i+ Err parazyd.org 70 i+ _message "An active swap partition is detected..." Err parazyd.org 70 i+ for s in $=swaps; do Err parazyd.org 70 i+ { _is_encrypted_block $s } && { r=2 } || { Err parazyd.org 70 i+ # We're dealing with unencrypted stuff. Err parazyd.org 70 i+ # Maybe it lives on an encrypted filesystem anyway. Err parazyd.org 70 i+ # @todo: verify it's actually on an encrypted FS (see #163 and !189) Err parazyd.org 70 i+ # Well, no: bail out. Err parazyd.org 70 i+ r=1; break Err parazyd.org 70 i+ } Err parazyd.org 70 i+ done Err parazyd.org 70 i+ Err parazyd.org 70 i+ if [[ $r -eq 2 ]]; then Err parazyd.org 70 i+ _success "All your swaps are belong to crypt. Good." Err parazyd.org 70 i+ else Err parazyd.org 70 i+ _warning "This poses a security risk." Err parazyd.org 70 i+ _warning "You can deactivate all swap partitions using the command:" Err parazyd.org 70 i+ _warning " swapoff -a" Err parazyd.org 70 i+ _warning "[#163] I may not detect plain swaps on an encrypted volume." Err parazyd.org 70 i+ _warning "But if you want to proceed like this, use the -f (force) flag." Err parazyd.org 70 i+ fi Err parazyd.org 70 i+ return $r Err parazyd.org 70 i+ Err parazyd.org 70 i+} Err parazyd.org 70 i+ Err parazyd.org 70 i+# Wrapper to allow encrypted swap and remind the user about possible Err parazyd.org 70 i+# data leaks to disk if swap is on, which shouldn't be ignored. It could Err parazyd.org 70 i+# be run once in main(), but as swap evolves, it's better to run it Err parazyd.org 70 i+# whenever swap may be needed. Err parazyd.org 70 i+# Exit if unencrypted swap is active on the system. Err parazyd.org 70 i+_check_swap() { Err parazyd.org 70 i+ if ! option_is_set -f && ! option_is_set --ignore-swap; then Err parazyd.org 70 i+ _ensure_safe_swap Err parazyd.org 70 i+ case $? in Err parazyd.org 70 i+ 0|2) # No, or encrypted swap Err parazyd.org 70 i+ return 0 Err parazyd.org 70 i+ ;; Err parazyd.org 70 i+ *) # Unencrypted swap Err parazyd.org 70 i+ _failure "Operation aborted." Err parazyd.org 70 i+ ;; Err parazyd.org 70 i+ esac Err parazyd.org 70 i+ fi Err parazyd.org 70 i+} Err parazyd.org 70 i+ Err parazyd.org 70 i+# Ask user for a password Err parazyd.org 70 i+# Wraps around the pinentry command, from the GnuPG project, as it Err parazyd.org 70 i+# provides better security and conveniently use the right toolkit. Err parazyd.org 70 i+ask_password() { Err parazyd.org 70 i+ Err parazyd.org 70 i+ local description="$1" Err parazyd.org 70 i+ local title="${2:-Enter tomb password.}" Err parazyd.org 70 i+ local output Err parazyd.org 70 i+ local password Err parazyd.org 70 i+ local gtkrc Err parazyd.org 70 i+ local theme Err parazyd.org 70 i+ Err parazyd.org 70 i+ # Distributions have broken wrappers for pinentry: they do Err parazyd.org 70 i+ # implement fallback, but they disrupt the output somehow. We are Err parazyd.org 70 i+ # better off relying on less intermediaries, so we implement our Err parazyd.org 70 i+ # own fallback mechanisms. Pinentry supported: curses, gtk-2, qt4 Err parazyd.org 70 i+ # and x11. Err parazyd.org 70 i+ Err parazyd.org 70 i+ # make sure LANG is set, default to C Err parazyd.org 70 i+ LANG=${LANG:-C} Err parazyd.org 70 i+ Err parazyd.org 70 i+ _verbose "asking password with tty=$TTY lc-ctype=$LANG" Err parazyd.org 70 i+ Err parazyd.org 70 i+ if [[ "$DISPLAY" = "" ]]; then Err parazyd.org 70 i+ Err parazyd.org 70 i+ if _is_found "pinentry-curses"; then Err parazyd.org 70 i+ _verbose "using pinentry-curses" Err parazyd.org 70 i+ output=`cat <." Err parazyd.org 70 i+} Err parazyd.org 70 i+ Err parazyd.org 70 i+ Err parazyd.org 70 i+# Check whether a commandline option is set. Err parazyd.org 70 i+# Err parazyd.org 70 i+# Synopsis: option_is_set -flag [out] Err parazyd.org 70 i+# Err parazyd.org 70 i+# First argument is the commandline flag (e.g., "-s"). Err parazyd.org 70 i+# If the second argument is present and set to 'out', print out the Err parazyd.org 70 i+# result: either 'set' or 'unset' (useful for if conditions). Err parazyd.org 70 i+# Err parazyd.org 70 i+# Return 0 if is set, 1 otherwise Err parazyd.org 70 i+option_is_set() { Err parazyd.org 70 i+ local -i r # the return code (0 = set, 1 = unset) Err parazyd.org 70 i+ Err parazyd.org 70 i+ [[ -n ${(k)OPTS[$1]} ]]; Err parazyd.org 70 i+ r=$? Err parazyd.org 70 i+ Err parazyd.org 70 i+ [[ $2 == "out" ]] && { Err parazyd.org 70 i+ [[ $r == 0 ]] && { print 'set' } || { print 'unset' } Err parazyd.org 70 i+ } Err parazyd.org 70 i+ Err parazyd.org 70 i+ return $r; Err parazyd.org 70 i+} Err parazyd.org 70 i+ Err parazyd.org 70 i+# Print the option value matching the given flag Err parazyd.org 70 i+# Unique argument is the commandline flag (e.g., "-s"). Err parazyd.org 70 i+option_value() { Err parazyd.org 70 i+ print -n - "${OPTS[$1]}" Err parazyd.org 70 i+} Err parazyd.org 70 i+ Err parazyd.org 70 i+# Messaging function with pretty coloring Err parazyd.org 70 i+function _msg() { Err parazyd.org 70 i+ local msg="$2" Err parazyd.org 70 i+ command -v gettext 1>/dev/null 2>/dev/null && msg="$(gettext -s "$2")" Err parazyd.org 70 i+ for i in $(seq 3 ${#}); Err parazyd.org 70 i+ do Err parazyd.org 70 i+ msg=${(S)msg//::$(($i - 2))*::/$*[$i]} Err parazyd.org 70 i+ done Err parazyd.org 70 i+ Err parazyd.org 70 i+ local command="print -P" Err parazyd.org 70 i+ local progname="$fg[magenta]${TOMBEXEC##*/}$reset_color" Err parazyd.org 70 i+ local message="$fg_bold[normal]$fg_no_bold[normal]$msg$reset_color" Err parazyd.org 70 i+ local -i returncode Err parazyd.org 70 i+ Err parazyd.org 70 i+ case "$1" in Err parazyd.org 70 i+ inline) Err parazyd.org 70 i+ command+=" -n"; pchars=" > "; pcolor="yellow" Err parazyd.org 70 i+ ;; Err parazyd.org 70 i+ message) Err parazyd.org 70 i+ pchars=" . "; pcolor="white"; message="$fg_no_bold[$pcolor]$msg$reset_color" Err parazyd.org 70 i+ ;; Err parazyd.org 70 i+ verbose) Err parazyd.org 70 i+ pchars="[D]"; pcolor="blue" Err parazyd.org 70 i+ ;; Err parazyd.org 70 i+ success) Err parazyd.org 70 i+ pchars="(*)"; pcolor="green"; message="$fg_no_bold[$pcolor]$msg$reset_color" Err parazyd.org 70 i+ ;; Err parazyd.org 70 i+ warning) Err parazyd.org 70 i+ pchars="[W]"; pcolor="yellow"; message="$fg_no_bold[$pcolor]$msg$reset_color" Err parazyd.org 70 i+ ;; Err parazyd.org 70 i+ failure) Err parazyd.org 70 i+ pchars="[E]"; pcolor="red"; message="$fg_no_bold[$pcolor]$msg$reset_color" Err parazyd.org 70 i+ returncode=1 Err parazyd.org 70 i+ ;; Err parazyd.org 70 i+ print) Err parazyd.org 70 i+ progname="" Err parazyd.org 70 i+ ;; Err parazyd.org 70 i+ *) Err parazyd.org 70 i+ pchars="[F]"; pcolor="red" Err parazyd.org 70 i+ message="Developer oops! Usage: _msg MESSAGE_TYPE \"MESSAGE_CONTENT\"" Err parazyd.org 70 i+ returncode=127 Err parazyd.org 70 i+ ;; Err parazyd.org 70 i+ esac Err parazyd.org 70 i+ ${=command} "${progname} $fg_bold[$pcolor]$pchars$reset_color ${message}$color[reset_color]" >&2 Err parazyd.org 70 i+ return $returncode Err parazyd.org 70 i+} Err parazyd.org 70 i+ Err parazyd.org 70 i+function _message say() { Err parazyd.org 70 i+ local notice="message" Err parazyd.org 70 i+ [[ "$1" = "-n" ]] && shift && notice="inline" Err parazyd.org 70 i+ option_is_set -q || _msg "$notice" $@ Err parazyd.org 70 i+ return 0 Err parazyd.org 70 i+} Err parazyd.org 70 i+ Err parazyd.org 70 i+function _verbose xxx() { Err parazyd.org 70 i+ option_is_set -D && _msg verbose $@ Err parazyd.org 70 i+ return 0 Err parazyd.org 70 i+} Err parazyd.org 70 i+ Err parazyd.org 70 i+function _success yes() { Err parazyd.org 70 i+ option_is_set -q || _msg success $@ Err parazyd.org 70 i+ return 0 Err parazyd.org 70 i+} Err parazyd.org 70 i+ Err parazyd.org 70 i+function _warning no() { Err parazyd.org 70 i+ option_is_set -q || _msg warning $@ Err parazyd.org 70 i+ return 1 Err parazyd.org 70 i+} Err parazyd.org 70 i+ Err parazyd.org 70 i+function _failure die() { Err parazyd.org 70 i+ typeset -i exitcode=${exitv:-1} Err parazyd.org 70 i+ option_is_set -q || _msg failure $@ Err parazyd.org 70 i+ # be sure we forget the secrets we were told Err parazyd.org 70 i+ exit $exitcode Err parazyd.org 70 i+} Err parazyd.org 70 i+ Err parazyd.org 70 i+function _print() { Err parazyd.org 70 i+ option_is_set -q || _msg print $@ Err parazyd.org 70 i+ return 0 Err parazyd.org 70 i+} Err parazyd.org 70 i+ Err parazyd.org 70 i+_list_optional_tools() { Err parazyd.org 70 i+ typeset -a _deps Err parazyd.org 70 i+ _deps=(gettext dcfldd wipe steghide) Err parazyd.org 70 i+ _deps+=(resize2fs tomb-kdb-pbkdf2 qrencode swish-e unoconv) Err parazyd.org 70 i+ for d in $_deps; do Err parazyd.org 70 i+ _print "`which $d`" Err parazyd.org 70 i+ done Err parazyd.org 70 i+ return 0 Err parazyd.org 70 i+} Err parazyd.org 70 i+ Err parazyd.org 70 i+ Err parazyd.org 70 i+# Check program dependencies Err parazyd.org 70 i+# Err parazyd.org 70 i+# Tomb depends on system utilities that must be present, and other Err parazyd.org 70 i+# functionality that can be provided by various programs according to Err parazyd.org 70 i+# what's available on the system. If some required commands are Err parazyd.org 70 i+# missing, bail out. Err parazyd.org 70 i+_ensure_dependencies() { Err parazyd.org 70 i+ Err parazyd.org 70 i+ # Check for required programs Err parazyd.org 70 i+ for req in cryptsetup pinentry sudo gpg mkfs.ext4 e2fsck; do Err parazyd.org 70 i+ command -v $req 1>/dev/null 2>/dev/null || { Err parazyd.org 70 i+ _failure "Missing required dependency ::1 command::. Please install it." $req } Err parazyd.org 70 i+ done Err parazyd.org 70 i+ Err parazyd.org 70 i+ # Ensure system binaries are available in the PATH Err parazyd.org 70 i+ path+=(/sbin /usr/sbin) # zsh magic Err parazyd.org 70 i+ Err parazyd.org 70 i+ # Which dd command to use Err parazyd.org 70 i+ command -v dcfldd 1>/dev/null 2>/dev/null && DD=(dcfldd statusinterval=1) Err parazyd.org 70 i+ Err parazyd.org 70 i+ # Which wipe command to use Err parazyd.org 70 i+ command -v wipe 1>/dev/null 2>/dev/null && WIPE=(wipe -f -s) Err parazyd.org 70 i+ Err parazyd.org 70 i+ # Check for steghide Err parazyd.org 70 i+ command -v steghide 1>/dev/null 2>/dev/null || STEGHIDE=0 Err parazyd.org 70 i+ # Check for resize Err parazyd.org 70 i+ command -v resize2fs 1>/dev/null 2>/dev/null || RESIZER=0 Err parazyd.org 70 i+ # Check for KDF auxiliary tools Err parazyd.org 70 i+ command -v tomb-kdb-pbkdf2 1>/dev/null 2>/dev/null || KDF=0 Err parazyd.org 70 i+ # Check for Swish-E file content indexer Err parazyd.org 70 i+ command -v swish-e 1>/dev/null 2>/dev/null || SWISH=0 Err parazyd.org 70 i+ # Check for QREncode for paper backups of keys Err parazyd.org 70 i+ command -v qrencode 1>/dev/null 2>/dev/null || QRENCODE=0 Err parazyd.org 70 i+} Err parazyd.org 70 i+ Err parazyd.org 70 i+# }}} - Commandline interaction Err parazyd.org 70 i+ Err parazyd.org 70 i+# {{{ Key operations Err parazyd.org 70 i+ Err parazyd.org 70 i+# $1 is the encrypted key contents we are checking Err parazyd.org 70 i+is_valid_key() { Err parazyd.org 70 i+ local key="$1" # Unique argument is an encrypted key to test Err parazyd.org 70 i+ Err parazyd.org 70 i+ _verbose "is_valid_key" Err parazyd.org 70 i+ Err parazyd.org 70 i+ [[ -z $key ]] && key=$TOMBKEY Err parazyd.org 70 i+ [[ "$key" = "cleartext" ]] && { Err parazyd.org 70 i+ { option_is_set --unsafe } || { Err parazyd.org 70 i+ _warning "cleartext key from stdin selected: this is unsafe." Err parazyd.org 70 i+ exitv=127 _failure "please use --unsafe if you really want to do this." Err parazyd.org 70 i+ } Err parazyd.org 70 i+ _warning "received key in cleartext from stdin (unsafe mode)" Err parazyd.org 70 i+ return 0 } Err parazyd.org 70 i+ Err parazyd.org 70 i+ [[ -z $key ]] && { Err parazyd.org 70 i+ _warning "is_valid_key() called without an argument." Err parazyd.org 70 i+ return 1 Err parazyd.org 70 i+ } Err parazyd.org 70 i+ Err parazyd.org 70 i+ # If the key file is an image don't check file header Err parazyd.org 70 i+ [[ -r $TOMBKEYFILE ]] \ Err parazyd.org 70 i+ && [[ $(file $TOMBKEYFILE) =~ "JP.G" ]] \ Err parazyd.org 70 i+ && { Err parazyd.org 70 i+ _message "Key is an image, it might be valid." Err parazyd.org 70 i+ return 0 } Err parazyd.org 70 i+ Err parazyd.org 70 i+ [[ $key =~ "BEGIN PGP" ]] && { Err parazyd.org 70 i+ _message "Key is valid." Err parazyd.org 70 i+ return 0 } Err parazyd.org 70 i+ Err parazyd.org 70 i+ return 1 Err parazyd.org 70 i+} Err parazyd.org 70 i+ Err parazyd.org 70 i+# $1 is a string containing an encrypted key Err parazyd.org 70 i+_tomb_key_recover recover_key() { Err parazyd.org 70 i+ local key="${1}" # Unique argument is an encrypted key Err parazyd.org 70 i+ Err parazyd.org 70 i+ _warning "Attempting key recovery." Err parazyd.org 70 i+ Err parazyd.org 70 i+ _head="${key[(f)1]}" # take the first line Err parazyd.org 70 i+ Err parazyd.org 70 i+ TOMBKEY="" # Reset global variable Err parazyd.org 70 i+ Err parazyd.org 70 i+ [[ $_head =~ "^_KDF_" ]] && TOMBKEY+="$_head\n" Err parazyd.org 70 i+ Err parazyd.org 70 i+ TOMBKEY+="-----BEGIN PGP MESSAGE-----\n" Err parazyd.org 70 i+ TOMBKEY+="$key\n" Err parazyd.org 70 i+ TOMBKEY+="-----END PGP MESSAGE-----\n" Err parazyd.org 70 i+ Err parazyd.org 70 i+ return 0 Err parazyd.org 70 i+} Err parazyd.org 70 i+ Err parazyd.org 70 i+# Retrieve the tomb key from the file specified from the command line, Err parazyd.org 70 i+# or from stdin if -k - was selected. Run validity checks on the Err parazyd.org 70 i+# file. On success, return 0 and print out the full path of the key. Err parazyd.org 70 i+# Set global variables TOMBKEY and TOMBKEYFILE. Err parazyd.org 70 i+_load_key() { Err parazyd.org 70 i+ local keyfile="$1" # Unique argument is an optional keyfile Err parazyd.org 70 i+ Err parazyd.org 70 i+ [[ -z $keyfile ]] && keyfile=$(option_value -k) Err parazyd.org 70 i+ [[ -z $keyfile ]] && { Err parazyd.org 70 i+ _failure "This operation requires a key file to be specified using the -k option." } Err parazyd.org 70 i+ Err parazyd.org 70 i+ if [[ $keyfile == "-" ]]; then Err parazyd.org 70 i+ _verbose "load_key reading from stdin." Err parazyd.org 70 i+ _message "Waiting for the key to be piped from stdin... " Err parazyd.org 70 i+ TOMBKEYFILE=stdin Err parazyd.org 70 i+ TOMBKEY=$(cat) Err parazyd.org 70 i+ elif [[ $keyfile == "cleartext" ]]; then Err parazyd.org 70 i+ _verbose "load_key reading SECRET from stdin" Err parazyd.org 70 i+ _message "Waiting for the key to be piped from stdin... " Err parazyd.org 70 i+ TOMBKEYFILE=cleartext Err parazyd.org 70 i+ TOMBKEY=cleartext Err parazyd.org 70 i+ TOMBSECRET=$(cat) Err parazyd.org 70 i+ else Err parazyd.org 70 i+ _verbose "load_key argument: ::1 key file::" $keyfile Err parazyd.org 70 i+ [[ -r $keyfile ]] || _failure "Key not found, specify one using -k." Err parazyd.org 70 i+ TOMBKEYFILE=$keyfile Err parazyd.org 70 i+ TOMBKEY="${mapfile[$TOMBKEYFILE]}" Err parazyd.org 70 i+ fi Err parazyd.org 70 i+ Err parazyd.org 70 i+ _verbose "load_key: ::1 key::" $TOMBKEYFILE Err parazyd.org 70 i+ Err parazyd.org 70 i+ [[ "$TOMBKEY" = "" ]] && { Err parazyd.org 70 i+ # something went wrong, there is no key to load Err parazyd.org 70 i+ # this occurs especially when piping from stdin and aborted Err parazyd.org 70 i+ _failure "Key not found, specify one using -k." Err parazyd.org 70 i+ } Err parazyd.org 70 i+ Err parazyd.org 70 i+ is_valid_key $TOMBKEY || { Err parazyd.org 70 i+ _warning "The key seems invalid or its format is not known by this version of Tomb." Err parazyd.org 70 i+ _tomb_key_recover $TOMBKEY Err parazyd.org 70 i+ } Err parazyd.org 70 i+ Err parazyd.org 70 i+ # Declared TOMBKEYFILE (path) Err parazyd.org 70 i+ # Declared TOMBKEY (contents) Err parazyd.org 70 i+ Err parazyd.org 70 i+ return 0 Err parazyd.org 70 i+} Err parazyd.org 70 i+ Err parazyd.org 70 i+# takes two args just like get_lukskey Err parazyd.org 70 i+# prints out the decrypted content Err parazyd.org 70 i+# contains tweaks for different gpg versions Err parazyd.org 70 i+gpg_decrypt() { Err parazyd.org 70 i+ # fix for gpg 1.4.11 where the --status-* options don't work ;^/ Err parazyd.org 70 i+ local gpgver=$(gpg --version --no-permission-warning | awk '/^gpg/ {print $3}') Err parazyd.org 70 i+ local gpgpass="$1\n$TOMBKEY" Err parazyd.org 70 i+ local gpgstatus Err parazyd.org 70 i+ Err parazyd.org 70 i+ [[ $gpgver == "1.4.11" ]] && { Err parazyd.org 70 i+ _verbose "GnuPG is version 1.4.11 - adopting status fix." Err parazyd.org 70 i+ Err parazyd.org 70 i+ TOMBSECRET=`print - "$gpgpass" | \ Err parazyd.org 70 i+ gpg --batch --passphrase-fd 0 --no-tty --no-options` Err parazyd.org 70 i+ ret=$? Err parazyd.org 70 i+ unset gpgpass Err parazyd.org 70 i+ Err parazyd.org 70 i+ } || { # using status-file in gpg != 1.4.11 Err parazyd.org 70 i+ Err parazyd.org 70 i+ TOMBSECRET=`print - "$gpgpass" | \ Err parazyd.org 70 i+ gpg --batch --passphrase-fd 0 --no-tty --no-options \ Err parazyd.org 70 i+ --status-fd 2 --no-mdc-warning --no-permission-warning \ Err parazyd.org 70 i+ --no-secmem-warning` |& grep GNUPG: \ Err parazyd.org 70 i+ | read -r -d'\n' gpgstatus Err parazyd.org 70 i+ Err parazyd.org 70 i+ unset gpgpass Err parazyd.org 70 i+ Err parazyd.org 70 i+ ret=1 Err parazyd.org 70 i+ Err parazyd.org 70 i+ [[ "${gpgstatus}" =~ "DECRYPTION_OKAY" ]] && { ret=0 } Err parazyd.org 70 i+ Err parazyd.org 70 i+ Err parazyd.org 70 i+ } Err parazyd.org 70 i+ return $ret Err parazyd.org 70 i+ Err parazyd.org 70 i+} Err parazyd.org 70 i+ Err parazyd.org 70 i+ Err parazyd.org 70 i+# Gets a key file and a password, prints out the decoded contents to Err parazyd.org 70 i+# be used directly by Luks as a cryptographic key Err parazyd.org 70 i+get_lukskey() { Err parazyd.org 70 i+ # $1 is the password Err parazyd.org 70 i+ _verbose "get_lukskey" Err parazyd.org 70 i+ Err parazyd.org 70 i+ _password="$1" Err parazyd.org 70 i+ Err parazyd.org 70 i+ Err parazyd.org 70 i+ firstline="${TOMBKEY[(f)1]}" Err parazyd.org 70 i+ Err parazyd.org 70 i+ # key is KDF encoded Err parazyd.org 70 i+ if [[ $firstline =~ '^_KDF_' ]]; then Err parazyd.org 70 i+ kdf_hash="${firstline[(ws:_:)2]}" Err parazyd.org 70 i+ _verbose "KDF: ::1 kdf::" "$kdf_hash" Err parazyd.org 70 i+ case "$kdf_hash" in Err parazyd.org 70 i+ "pbkdf2sha1") Err parazyd.org 70 i+ kdf_salt="${firstline[(ws:_:)3]}" Err parazyd.org 70 i+ kdf_ic="${firstline[(ws:_:)4]}" Err parazyd.org 70 i+ kdf_len="${firstline[(ws:_:)5]}" Err parazyd.org 70 i+ _message "Unlocking KDF key protection ($kdf_hash)" Err parazyd.org 70 i+ _verbose "KDF salt: $kdf_salt" Err parazyd.org 70 i+ _verbose "KDF ic: $kdf_ic" Err parazyd.org 70 i+ _verbose "KDF len: $kdf_len" Err parazyd.org 70 i+ _password=$(tomb-kdb-pbkdf2 $kdf_salt $kdf_ic $kdf_len 2>/dev/null <<<$_password) Err parazyd.org 70 i+ ;; Err parazyd.org 70 i+ *) Err parazyd.org 70 i+ _failure "No suitable program for KDF ::1 program::." $pbkdf_hash Err parazyd.org 70 i+ unset _password Err parazyd.org 70 i+ return 1 Err parazyd.org 70 i+ ;; Err parazyd.org 70 i+ esac Err parazyd.org 70 i+ Err parazyd.org 70 i+ # key needs to be exhumed from an image Err parazyd.org 70 i+ elif [[ -r $TOMBKEYFILE && $(file $TOMBKEYFILE) =~ "JP.G" ]]; then Err parazyd.org 70 i+ Err parazyd.org 70 i+ exhume_key $TOMBKEYFILE "$_password" Err parazyd.org 70 i+ Err parazyd.org 70 i+ fi Err parazyd.org 70 i+ Err parazyd.org 70 i+ gpg_decrypt "$_password" # Save decrypted contents into $TOMBSECRET Err parazyd.org 70 i+ Err parazyd.org 70 i+ ret="$?" Err parazyd.org 70 i+ Err parazyd.org 70 i+ _verbose "get_lukskey returns ::1::" $ret Err parazyd.org 70 i+ return $ret Err parazyd.org 70 i+} Err parazyd.org 70 i+ Err parazyd.org 70 i+# This function asks the user for the password to use the key it tests Err parazyd.org 70 i+# it against the return code of gpg on success returns 0 and saves Err parazyd.org 70 i+# the password in the global variable $TOMBPASSWORD Err parazyd.org 70 i+ask_key_password() { Err parazyd.org 70 i+ [[ -z "$TOMBKEYFILE" ]] && { Err parazyd.org 70 i+ _failure "Internal error: ask_key_password() called before _load_key()." } Err parazyd.org 70 i+ Err parazyd.org 70 i+ [[ "$TOMBKEYFILE" = "cleartext" ]] && { Err parazyd.org 70 i+ _verbose "no password needed, using secret bytes from stdin" Err parazyd.org 70 i+ return 0 } Err parazyd.org 70 i+ Err parazyd.org 70 i+ _message "A password is required to use key ::1 key::" $TOMBKEYFILE Err parazyd.org 70 i+ passok=0 Err parazyd.org 70 i+ tombpass="" Err parazyd.org 70 i+ if [[ "$1" = "" ]]; then Err parazyd.org 70 i+ Err parazyd.org 70 i+ for c in 1 2 3; do Err parazyd.org 70 i+ if [[ $c == 1 ]]; then Err parazyd.org 70 i+ tombpass=$(ask_password "Insert password to: $TOMBKEYFILE") Err parazyd.org 70 i+ else Err parazyd.org 70 i+ tombpass=$(ask_password "Insert password to: $TOMBKEYFILE (attempt $c)") Err parazyd.org 70 i+ fi Err parazyd.org 70 i+ [[ $? = 0 ]] || { Err parazyd.org 70 i+ _warning "User aborted password dialog." Err parazyd.org 70 i+ return 1 Err parazyd.org 70 i+ } Err parazyd.org 70 i+ Err parazyd.org 70 i+ get_lukskey "$tombpass" Err parazyd.org 70 i+ Err parazyd.org 70 i+ [[ $? = 0 ]] && { Err parazyd.org 70 i+ passok=1; _message "Password OK." Err parazyd.org 70 i+ break; Err parazyd.org 70 i+ } Err parazyd.org 70 i+ done Err parazyd.org 70 i+ Err parazyd.org 70 i+ else Err parazyd.org 70 i+ # if a second argument is present then the password is already known Err parazyd.org 70 i+ tombpass="$1" Err parazyd.org 70 i+ _verbose "ask_key_password with tombpass: ::1 tomb pass::" $tombpass Err parazyd.org 70 i+ Err parazyd.org 70 i+ get_lukskey "$tombpass" Err parazyd.org 70 i+ Err parazyd.org 70 i+ [[ $? = 0 ]] && { Err parazyd.org 70 i+ passok=1; _message "Password OK." Err parazyd.org 70 i+ } Err parazyd.org 70 i+ Err parazyd.org 70 i+ fi Err parazyd.org 70 i+ [[ $passok == 1 ]] || return 1 Err parazyd.org 70 i+ Err parazyd.org 70 i+ TOMBPASSWORD=$tombpass Err parazyd.org 70 i+ return 0 Err parazyd.org 70 i+} Err parazyd.org 70 i+ Err parazyd.org 70 i+# call cryptsetup with arguments using the currently known secret Err parazyd.org 70 i+# echo flags eliminate newline and disable escape (BSD_ECHO) Err parazyd.org 70 i+_cryptsetup() { Err parazyd.org 70 i+ print -R -n - "$TOMBSECRET" | _sudo cryptsetup --key-file - ${=@} Err parazyd.org 70 i+ return $? Err parazyd.org 70 i+} Err parazyd.org 70 i+ Err parazyd.org 70 i+# change tomb key password Err parazyd.org 70 i+change_passwd() { Err parazyd.org 70 i+ local tmpnewkey lukskey c tombpass tombpasstmp Err parazyd.org 70 i+ Err parazyd.org 70 i+ _check_swap # Ensure swap is secure, if any Err parazyd.org 70 i+ _load_key # Try loading key from option -k and set TOMBKEYFILE Err parazyd.org 70 i+ Err parazyd.org 70 i+ _message "Commanded to change password for tomb key ::1 key::" $TOMBKEYFILE Err parazyd.org 70 i+ Err parazyd.org 70 i+ _tmp_create Err parazyd.org 70 i+ tmpnewkey=$TOMBTMP Err parazyd.org 70 i+ Err parazyd.org 70 i+ if option_is_set --tomb-old-pwd; then Err parazyd.org 70 i+ local tomboldpwd="`option_value --tomb-old-pwd`" Err parazyd.org 70 i+ _verbose "tomb-old-pwd = ::1 old pass::" $tomboldpwd Err parazyd.org 70 i+ ask_key_password "$tomboldpwd" Err parazyd.org 70 i+ else Err parazyd.org 70 i+ ask_key_password Err parazyd.org 70 i+ fi Err parazyd.org 70 i+ [[ $? == 0 ]] || _failure "No valid password supplied." Err parazyd.org 70 i+ Err parazyd.org 70 i+ _success "Changing password for ::1 key file::" $TOMBKEYFILE Err parazyd.org 70 i+ Err parazyd.org 70 i+ # Here $TOMBSECRET contains the key material in clear Err parazyd.org 70 i+ Err parazyd.org 70 i+ { option_is_set --tomb-pwd } && { Err parazyd.org 70 i+ local tombpwd="`option_value --tomb-pwd`" Err parazyd.org 70 i+ _verbose "tomb-pwd = ::1 new pass::" $tombpwd Err parazyd.org 70 i+ gen_key "$tombpwd" >> "$tmpnewkey" Err parazyd.org 70 i+ } || { Err parazyd.org 70 i+ gen_key >> "$tmpnewkey" Err parazyd.org 70 i+ } Err parazyd.org 70 i+ Err parazyd.org 70 i+ { is_valid_key "${mapfile[$tmpnewkey]}" } || { Err parazyd.org 70 i+ _failure "Error: the newly generated keyfile does not seem valid." } Err parazyd.org 70 i+ Err parazyd.org 70 i+ # Copy the new key as the original keyfile name Err parazyd.org 70 i+ cp -f "${tmpnewkey}" $TOMBKEYFILE Err parazyd.org 70 i+ _success "Your passphrase was successfully updated." Err parazyd.org 70 i+ Err parazyd.org 70 i+ return 0 Err parazyd.org 70 i+} Err parazyd.org 70 i+ Err parazyd.org 70 i+ Err parazyd.org 70 i+# takes care to encrypt a key Err parazyd.org 70 i+# honored options: --kdf --tomb-pwd -o Err parazyd.org 70 i+gen_key() { Err parazyd.org 70 i+ # $1 the password to use; if not set ask user Err parazyd.org 70 i+ # -o is the --cipher-algo to use (string taken by GnuPG) Err parazyd.org 70 i+ local algopt="`option_value -o`" Err parazyd.org 70 i+ local algo="${algopt:-AES256}" Err parazyd.org 70 i+ # here user is prompted for key password Err parazyd.org 70 i+ tombpass="" Err parazyd.org 70 i+ tombpasstmp="" Err parazyd.org 70 i+ Err parazyd.org 70 i+ if [ "$1" = "" ]; then Err parazyd.org 70 i+ while true; do Err parazyd.org 70 i+ # 3 tries to write two times a matching password Err parazyd.org 70 i+ tombpass=`ask_password "Type the new password to secure your key"` Err parazyd.org 70 i+ if [[ $? != 0 ]]; then Err parazyd.org 70 i+ _failure "User aborted." Err parazyd.org 70 i+ fi Err parazyd.org 70 i+ if [ -z $tombpass ]; then Err parazyd.org 70 i+ _failure "You set empty password, which is not possible." Err parazyd.org 70 i+ fi Err parazyd.org 70 i+ tombpasstmp=$tombpass Err parazyd.org 70 i+ tombpass=`ask_password "Type the new password to secure your key (again)"` Err parazyd.org 70 i+ if [[ $? != 0 ]]; then Err parazyd.org 70 i+ _failure "User aborted." Err parazyd.org 70 i+ fi Err parazyd.org 70 i+ if [ "$tombpasstmp" = "$tombpass" ]; then Err parazyd.org 70 i+ break; Err parazyd.org 70 i+ fi Err parazyd.org 70 i+ unset tombpasstmp Err parazyd.org 70 i+ unset tombpass Err parazyd.org 70 i+ done Err parazyd.org 70 i+ else Err parazyd.org 70 i+ tombpass="$1" Err parazyd.org 70 i+ _verbose "gen_key takes tombpass from CLI argument: ::1 tomb pass::" $tombpass Err parazyd.org 70 i+ fi Err parazyd.org 70 i+ Err parazyd.org 70 i+ header="" Err parazyd.org 70 i+ [[ $KDF == 1 ]] && { Err parazyd.org 70 i+ { option_is_set --kdf } && { Err parazyd.org 70 i+ # KDF is a new key strenghtening technique against brute forcing Err parazyd.org 70 i+ # see: https://github.com/dyne/Tomb/issues/82 Err parazyd.org 70 i+ itertime="`option_value --kdf`" Err parazyd.org 70 i+ # removing support of floating points because they can't be type checked well Err parazyd.org 70 i+ if [[ "$itertime" != <-> ]]; then Err parazyd.org 70 i+ unset tombpass Err parazyd.org 70 i+ unset tombpasstmp Err parazyd.org 70 i+ _error "Wrong argument for --kdf: must be an integer number (iteration seconds)." Err parazyd.org 70 i+ _error "Depending on the speed of machines using this tomb, use 1 to 10, or more" Err parazyd.org 70 i+ return 1 Err parazyd.org 70 i+ fi Err parazyd.org 70 i+ # --kdf takes one parameter: iter time (on present machine) in seconds Err parazyd.org 70 i+ local -i microseconds Err parazyd.org 70 i+ microseconds=$(( itertime * 1000000 )) Err parazyd.org 70 i+ _success "Using KDF, iteration time: ::1 microseconds::" $microseconds Err parazyd.org 70 i+ _message "generating salt" Err parazyd.org 70 i+ pbkdf2_salt=`tomb-kdb-pbkdf2-gensalt` Err parazyd.org 70 i+ _message "calculating iterations" Err parazyd.org 70 i+ pbkdf2_iter=`tomb-kdb-pbkdf2-getiter $microseconds` Err parazyd.org 70 i+ _message "encoding the password" Err parazyd.org 70 i+ # We use a length of 64bytes = 512bits (more than needed!?) Err parazyd.org 70 i+ tombpass=`tomb-kdb-pbkdf2 $pbkdf2_salt $pbkdf2_iter 64 <<<"${tombpass}"` Err parazyd.org 70 i+ Err parazyd.org 70 i+ header="_KDF_pbkdf2sha1_${pbkdf2_salt}_${pbkdf2_iter}_64\n" Err parazyd.org 70 i+ } Err parazyd.org 70 i+ } Err parazyd.org 70 i+ Err parazyd.org 70 i+ Err parazyd.org 70 i+ print $header Err parazyd.org 70 i+ Err parazyd.org 70 i+ # TODO: check result of gpg operation Err parazyd.org 70 i+ cat </dev/null || _failure "gpg (GnuPG) is not found, Tomb cannot function without it." Err parazyd.org 70 i+ Err parazyd.org 70 i+ ciphers=(`gpg --version | awk ' Err parazyd.org 70 i+BEGIN { ciphers=0 } Err parazyd.org 70 i+/^Cipher:/ { gsub(/,/,""); sub(/^Cipher:/,""); print; ciphers=1; next } Err parazyd.org 70 i+/^Hash:/ { ciphers=0 } Err parazyd.org 70 i+{ if(ciphers==0) { next } else { gsub(/,/,""); print; } } Err parazyd.org 70 i+'`) Err parazyd.org 70 i+ print " ${ciphers}" Err parazyd.org 70 i+ return 1 Err parazyd.org 70 i+} Err parazyd.org 70 i+ Err parazyd.org 70 i+# Steganographic function to bury a key inside an image. Err parazyd.org 70 i+# Requires steghide(1) to be installed Err parazyd.org 70 i+bury_key() { Err parazyd.org 70 i+ Err parazyd.org 70 i+ _load_key # Try loading key from option -k and set TOMBKEY Err parazyd.org 70 i+ Err parazyd.org 70 i+ imagefile=$PARAM Err parazyd.org 70 i+ Err parazyd.org 70 i+ [[ "`file $imagefile`" =~ "JPEG" ]] || { Err parazyd.org 70 i+ _warning "Encode failed: ::1 image file:: is not a jpeg image." $imagefile Err parazyd.org 70 i+ return 1 Err parazyd.org 70 i+ } Err parazyd.org 70 i+ Err parazyd.org 70 i+ _success "Encoding key ::1 tomb key:: inside image ::2 image file::" $TOMBKEY $imagefile Err parazyd.org 70 i+ _message "Please confirm the key password for the encoding" Err parazyd.org 70 i+ # We ask the password and test if it is the same encoding the Err parazyd.org 70 i+ # base key, to insure that the same password is used for the Err parazyd.org 70 i+ # encryption and the steganography. This is a standard enforced Err parazyd.org 70 i+ # by Tomb, but it isn't strictly necessary (and having different Err parazyd.org 70 i+ # password would enhance security). Nevertheless here we prefer Err parazyd.org 70 i+ # usability. Err parazyd.org 70 i+ Err parazyd.org 70 i+ { option_is_set --tomb-pwd } && { Err parazyd.org 70 i+ local tombpwd="`option_value --tomb-pwd`" Err parazyd.org 70 i+ _verbose "tomb-pwd = ::1 tomb pass::" $tombpwd Err parazyd.org 70 i+ ask_key_password "$tombpwd" Err parazyd.org 70 i+ } || { Err parazyd.org 70 i+ ask_key_password Err parazyd.org 70 i+ } Err parazyd.org 70 i+ [[ $? != 0 ]] && { Err parazyd.org 70 i+ _warning "Wrong password supplied." Err parazyd.org 70 i+ _failure "You shall not bury a key whose password is unknown to you." } Err parazyd.org 70 i+ Err parazyd.org 70 i+ # We omit armor strings since having them as constants can give Err parazyd.org 70 i+ # ground to effective attacks on steganography Err parazyd.org 70 i+ print - "$TOMBKEY" | awk ' Err parazyd.org 70 i+/^-----/ {next} Err parazyd.org 70 i+/^Version/ {next} Err parazyd.org 70 i+{print $0}' \ Err parazyd.org 70 i+ | steghide embed --embedfile - --coverfile ${imagefile} \ Err parazyd.org 70 i+ -p $TOMBPASSWORD -z 9 -e serpent cbc Err parazyd.org 70 i+ if [ $? != 0 ]; then Err parazyd.org 70 i+ _warning "Encoding error: steghide reports problems." Err parazyd.org 70 i+ res=1 Err parazyd.org 70 i+ else Err parazyd.org 70 i+ _success "Tomb key encoded succesfully into image ::1 image file::" $imagefile Err parazyd.org 70 i+ res=0 Err parazyd.org 70 i+ fi Err parazyd.org 70 i+ Err parazyd.org 70 i+ return $res Err parazyd.org 70 i+} Err parazyd.org 70 i+ Err parazyd.org 70 i+# mandatory 1st arg: the image file where key is supposed to be Err parazyd.org 70 i+# optional 2nd arg: the password to use (same as key, internal use) Err parazyd.org 70 i+# optional 3rd arg: the key where to save the result (- for stdout) Err parazyd.org 70 i+exhume_key() { Err parazyd.org 70 i+ [[ "$1" = "" ]] && { Err parazyd.org 70 i+ _failure "Exhume failed, no image specified" } Err parazyd.org 70 i+ Err parazyd.org 70 i+ local imagefile="$1" # The image file where to look for the key Err parazyd.org 70 i+ local tombpass="$2" # (Optional) the password to use (internal use) Err parazyd.org 70 i+ local destkey="$3" # (Optional) the key file where to save the Err parazyd.org 70 i+ # result (- for stdout) Err parazyd.org 70 i+ local r=1 # Return code (default: fail) Err parazyd.org 70 i+ Err parazyd.org 70 i+ # Ensure the image file is a readable JPEG Err parazyd.org 70 i+ [[ ! -r $imagefile ]] && { Err parazyd.org 70 i+ _failure "Exhume failed, image file not found: ::1 image file::" "${imagefile:-none}" } Err parazyd.org 70 i+ [[ ! $(file "$imagefile") =~ "JP.G" ]] && { Err parazyd.org 70 i+ _failure "Exhume failed: ::1 image file:: is not a jpeg image." $imagefile } Err parazyd.org 70 i+ Err parazyd.org 70 i+ # When a password is passed as argument then always print out Err parazyd.org 70 i+ # the exhumed key on stdout without further checks (internal use) Err parazyd.org 70 i+ [[ -n "$tombpass" ]] && { Err parazyd.org 70 i+ TOMBKEY=$(steghide extract -sf $imagefile -p $tombpass -xf -) Err parazyd.org 70 i+ [[ $? != 0 ]] && { Err parazyd.org 70 i+ _failure "Wrong password or no steganographic key found" } Err parazyd.org 70 i+ Err parazyd.org 70 i+ recover_key $TOMBKEY Err parazyd.org 70 i+ Err parazyd.org 70 i+ return 0 Err parazyd.org 70 i+ } Err parazyd.org 70 i+ Err parazyd.org 70 i+ # Ensure we have a valid destination for the key Err parazyd.org 70 i+ [[ -z $destkey ]] && { option_is_set -k } && destkey=$(option_value -k) Err parazyd.org 70 i+ [[ -z $destkey ]] && { Err parazyd.org 70 i+ destkey="-" # No key was specified: fallback to stdout Err parazyd.org 70 i+ _message "printing exhumed key on stdout" } Err parazyd.org 70 i+ Err parazyd.org 70 i+ # Bail out if destination exists, unless -f (force) was passed Err parazyd.org 70 i+ [[ $destkey != "-" && -s $destkey ]] && { Err parazyd.org 70 i+ _warning "File exists: ::1 tomb key::" $destkey Err parazyd.org 70 i+ { option_is_set -f } && { Err parazyd.org 70 i+ _warning "Use of --force selected: overwriting." Err parazyd.org 70 i+ rm -f $destkey Err parazyd.org 70 i+ } || { Err parazyd.org 70 i+ _warning "Make explicit use of --force to overwrite." Err parazyd.org 70 i+ _failure "Refusing to overwrite file. Operation aborted." } Err parazyd.org 70 i+ } Err parazyd.org 70 i+ Err parazyd.org 70 i+ _message "Trying to exhume a key out of image ::1 image file::" $imagefile Err parazyd.org 70 i+ { option_is_set --tomb-pwd } && { Err parazyd.org 70 i+ tombpass=$(option_value --tomb-pwd) Err parazyd.org 70 i+ _verbose "tomb-pwd = ::1 tomb pass::" $tombpass Err parazyd.org 70 i+ } || { Err parazyd.org 70 i+ [[ -n $TOMBPASSWORD ]] && tombpass=$TOMBPASSWORD Err parazyd.org 70 i+ } || { Err parazyd.org 70 i+ tombpass=$(ask_password "Insert password to exhume key from $imagefile") Err parazyd.org 70 i+ [[ $? != 0 ]] && { Err parazyd.org 70 i+ _warning "User aborted password dialog." Err parazyd.org 70 i+ return 1 Err parazyd.org 70 i+ } Err parazyd.org 70 i+ } Err parazyd.org 70 i+ Err parazyd.org 70 i+ # Extract the key from the image Err parazyd.org 70 i+ steghide extract -sf $imagefile -p ${tombpass} -xf $destkey Err parazyd.org 70 i+ r=$? Err parazyd.org 70 i+ Err parazyd.org 70 i+ # Report to the user Err parazyd.org 70 i+ [[ "$destkey" = "-" ]] && destkey="stdout" Err parazyd.org 70 i+ [[ $r == 0 ]] && { Err parazyd.org 70 i+ _success "Key succesfully exhumed to ::1 key::." $destkey Err parazyd.org 70 i+ } || { Err parazyd.org 70 i+ _warning "Nothing found in ::1 image file::" $imagefile Err parazyd.org 70 i+ } Err parazyd.org 70 i+ Err parazyd.org 70 i+ return $r Err parazyd.org 70 i+} Err parazyd.org 70 i+ Err parazyd.org 70 i+# Produces a printable image of the key contents so a backup on paper Err parazyd.org 70 i+# can be made and hidden in books etc. Err parazyd.org 70 i+engrave_key() { Err parazyd.org 70 i+ Err parazyd.org 70 i+ _load_key # Try loading key from option -k and set TOMBKEYFILE Err parazyd.org 70 i+ Err parazyd.org 70 i+ local keyname=$(basename $TOMBKEYFILE) Err parazyd.org 70 i+ local pngname="$keyname.qr.png" Err parazyd.org 70 i+ Err parazyd.org 70 i+ _success "Rendering a printable QRCode for key: ::1 tomb key file::" $TOMBKEYFILE Err parazyd.org 70 i+ # we omit armor strings to save space Err parazyd.org 70 i+ awk '/^-----/ {next}; /^Version/ {next}; {print $0}' $TOMBKEYFILE \ Err parazyd.org 70 i+ | qrencode --size 4 --level H --casesensitive -o $pngname Err parazyd.org 70 i+ [[ $? != 0 ]] && { Err parazyd.org 70 i+ _failure "QREncode reported an error." } Err parazyd.org 70 i+ Err parazyd.org 70 i+ _success "Operation successful:" Err parazyd.org 70 i+ # TODO: only if verbose and/or not silent Err parazyd.org 70 i+ ls -lh $pngname Err parazyd.org 70 i+ file $pngname Err parazyd.org 70 i+} Err parazyd.org 70 i+ Err parazyd.org 70 i+# }}} - Key handling Err parazyd.org 70 i+ Err parazyd.org 70 i+# {{{ Create Err parazyd.org 70 i+ Err parazyd.org 70 i+# Since version 1.5.3, tomb creation is a three-step process that replaces create_tomb(): Err parazyd.org 70 i+# Err parazyd.org 70 i+# * dig a .tomb (the large file) using /dev/urandom (takes some minutes at least) Err parazyd.org 70 i+# Err parazyd.org 70 i+# * forge a .key (the small file) using /dev/random (good entropy needed) Err parazyd.org 70 i+# Err parazyd.org 70 i+# * lock the .tomb file with the key, binding the key to the tomb (requires dm_crypt format) Err parazyd.org 70 i+ Err parazyd.org 70 i+# Step one - Dig a tomb Err parazyd.org 70 i+# Err parazyd.org 70 i+# Synopsis: dig_tomb /path/to/tomb -s sizemebibytes Err parazyd.org 70 i+# Err parazyd.org 70 i+# It will create an empty file to be formatted as a loopback Err parazyd.org 70 i+# filesystem. Initially the file is filled with random data taken Err parazyd.org 70 i+# from /dev/urandom to improve overall tomb's security and prevent Err parazyd.org 70 i+# some attacks aiming at detecting how much data is in the tomb, or Err parazyd.org 70 i+# which blocks in the filesystem contain that data. Err parazyd.org 70 i+ Err parazyd.org 70 i+dig_tomb() { Err parazyd.org 70 i+ local tombpath="$1" # Path to tomb Err parazyd.org 70 i+ # Require the specification of the size of the tomb (-s) in MiB Err parazyd.org 70 i+ local -i tombsize=$(option_value -s) Err parazyd.org 70 i+ Err parazyd.org 70 i+ _message "Commanded to dig tomb ::1 tomb path::" $tombpath Err parazyd.org 70 i+ Err parazyd.org 70 i+ [[ -n "$tombpath" ]] || _failure "Missing path to tomb" Err parazyd.org 70 i+ [[ -n "$tombsize" ]] || _failure "Size argument missing, use -s" Err parazyd.org 70 i+ [[ $tombsize == <-> ]] || _failure "Size must be an integer (mebibytes)" Err parazyd.org 70 i+ [[ $tombsize -ge 10 ]] || _failure "Tombs can't be smaller than 10 mebibytes" Err parazyd.org 70 i+ Err parazyd.org 70 i+ _plot $tombpath # Set TOMB{PATH,DIR,FILE,NAME} Err parazyd.org 70 i+ Err parazyd.org 70 i+ [[ -e $TOMBPATH ]] && { Err parazyd.org 70 i+ _warning "A tomb exists already. I'm not digging here:" Err parazyd.org 70 i+ ls -lh $TOMBPATH Err parazyd.org 70 i+ return 1 Err parazyd.org 70 i+ } Err parazyd.org 70 i+ Err parazyd.org 70 i+ _success "Creating a new tomb in ::1 tomb path::" $TOMBPATH Err parazyd.org 70 i+ Err parazyd.org 70 i+ _message "Generating ::1 tomb file:: of ::2 size::MiB" $TOMBFILE $tombsize Err parazyd.org 70 i+ Err parazyd.org 70 i+ # Ensure that file permissions are safe even if interrupted Err parazyd.org 70 i+ touch $TOMBPATH Err parazyd.org 70 i+ [[ $? = 0 ]] || { Err parazyd.org 70 i+ _warning "Error creating the tomb ::1 tomb path::" $TOMBPATH Err parazyd.org 70 i+ _failure "Operation aborted." Err parazyd.org 70 i+ } Err parazyd.org 70 i+ chmod 0600 $TOMBPATH Err parazyd.org 70 i+ Err parazyd.org 70 i+ _verbose "Data dump using ::1:: from /dev/urandom" ${DD[1]} Err parazyd.org 70 i+ ${=DD} if=/dev/urandom bs=1048576 count=$tombsize of=$TOMBPATH Err parazyd.org 70 i+ Err parazyd.org 70 i+ [[ $? == 0 && -e $TOMBPATH ]] && { Err parazyd.org 70 i+ ls -lh $TOMBPATH Err parazyd.org 70 i+ } || { Err parazyd.org 70 i+ _warning "Error creating the tomb ::1 tomb path::" $TOMBPATH Err parazyd.org 70 i+ _failure "Operation aborted." Err parazyd.org 70 i+ } Err parazyd.org 70 i+ Err parazyd.org 70 i+ _success "Done digging ::1 tomb name::" $TOMBNAME Err parazyd.org 70 i+ _message "Your tomb is not yet ready, you need to forge a key and lock it:" Err parazyd.org 70 i+ _message "tomb forge ::1 tomb path::.key" $TOMBPATH Err parazyd.org 70 i+ _message "tomb lock ::1 tomb path:: -k ::1 tomb path::.key" $TOMBPATH Err parazyd.org 70 i+ Err parazyd.org 70 i+ return 0 Err parazyd.org 70 i+} Err parazyd.org 70 i+ Err parazyd.org 70 i+# Step two -- Create a detached key to lock a tomb with Err parazyd.org 70 i+# Err parazyd.org 70 i+# Synopsis: forge_key [destkey|-k destkey] [-o cipher] Err parazyd.org 70 i+# Err parazyd.org 70 i+# Arguments: Err parazyd.org 70 i+# -k path to destination keyfile Err parazyd.org 70 i+# -o Use an alternate algorithm Err parazyd.org 70 i+# Err parazyd.org 70 i+forge_key() { Err parazyd.org 70 i+ # can be specified both as simple argument or using -k Err parazyd.org 70 i+ local destkey="$1" Err parazyd.org 70 i+ { option_is_set -k } && { destkey=$(option_value -k) } Err parazyd.org 70 i+ Err parazyd.org 70 i+ local algo="AES256" # Default encryption algorithm Err parazyd.org 70 i+ Err parazyd.org 70 i+ [[ -z "$destkey" ]] && { Err parazyd.org 70 i+ _failure "A filename needs to be specified using -k to forge a new key." } Err parazyd.org 70 i+ Err parazyd.org 70 i+# _message "Commanded to forge key ::1 key::" $destkey Err parazyd.org 70 i+ Err parazyd.org 70 i+ _check_swap # Ensure the available memory is safe to use Err parazyd.org 70 i+ Err parazyd.org 70 i+ # Ensure GnuPG won't exit with an error before first run Err parazyd.org 70 i+ [[ -r $HOME/.gnupg/pubring.gpg ]] || { Err parazyd.org 70 i+ mkdir -m 0700 $HOME/.gnupg Err parazyd.org 70 i+ touch $HOME/.gnupg/pubring.gpg } Err parazyd.org 70 i+ Err parazyd.org 70 i+ # Do not overwrite any files accidentally Err parazyd.org 70 i+ [[ -r "$destkey" ]] && { Err parazyd.org 70 i+ ls -lh $destkey Err parazyd.org 70 i+ _failure "Forging this key would overwrite an existing file. Operation aborted." } Err parazyd.org 70 i+ Err parazyd.org 70 i+ touch $destkey Err parazyd.org 70 i+ [[ $? == 0 ]] || { Err parazyd.org 70 i+ _warning "Cannot generate encryption key." Err parazyd.org 70 i+ _failure "Operation aborted." } Err parazyd.org 70 i+ chmod 0600 $destkey Err parazyd.org 70 i+ Err parazyd.org 70 i+ # Update algorithm if it was passed on the command line with -o Err parazyd.org 70 i+ { option_is_set -o } && algopt="$(option_value -o)" Err parazyd.org 70 i+ [[ -n "$algopt" ]] && algo=$algopt Err parazyd.org 70 i+ Err parazyd.org 70 i+ _message "Commanded to forge key ::1 key:: with cipher algorithm ::2 algorithm::" \ Err parazyd.org 70 i+ $destkey $algo Err parazyd.org 70 i+ Err parazyd.org 70 i+ [[ $KDF == 1 ]] && { Err parazyd.org 70 i+ _message "Using KDF to protect the key password (`option_value --kdf` rounds)" Err parazyd.org 70 i+ } Err parazyd.org 70 i+ Err parazyd.org 70 i+ TOMBKEYFILE="$destkey" # Set global variable Err parazyd.org 70 i+ Err parazyd.org 70 i+ _warning "This operation takes time, keep using this computer on other tasks," Err parazyd.org 70 i+ _warning "once done you will be asked to choose a password for your tomb." Err parazyd.org 70 i+ _warning "To make it faster you can move the mouse around." Err parazyd.org 70 i+ _warning "If you are on a server, you can use an Entropy Generation Daemon." Err parazyd.org 70 i+ Err parazyd.org 70 i+ # Use /dev/random as the entropy source, unless --use-urandom is specified Err parazyd.org 70 i+ local random_source=/dev/random Err parazyd.org 70 i+ { option_is_set --use-urandom } && random_source=/dev/urandom Err parazyd.org 70 i+ Err parazyd.org 70 i+ _verbose "Data dump using ::1:: from ::2 source::" ${DD[1]} $random_source Err parazyd.org 70 i+ TOMBSECRET=$(${=DD} bs=1 count=256 if=$random_source) Err parazyd.org 70 i+ [[ $? == 0 ]] || { Err parazyd.org 70 i+ _warning "Cannot generate encryption key." Err parazyd.org 70 i+ _failure "Operation aborted." } Err parazyd.org 70 i+ Err parazyd.org 70 i+ # Here the global variable TOMBSECRET contains the naked secret Err parazyd.org 70 i+ Err parazyd.org 70 i+ _success "Choose the password of your key: ::1 tomb key::" $TOMBKEYFILE Err parazyd.org 70 i+ _message "(You can also change it later using 'tomb passwd'.)" Err parazyd.org 70 i+ # _user_file $TOMBKEYFILE Err parazyd.org 70 i+ Err parazyd.org 70 i+ tombname="$TOMBKEYFILE" # XXX ??? Err parazyd.org 70 i+ # the gen_key() function takes care of the new key's encryption Err parazyd.org 70 i+ { option_is_set --tomb-pwd } && { Err parazyd.org 70 i+ local tombpwd="`option_value --tomb-pwd`" Err parazyd.org 70 i+ _verbose "tomb-pwd = ::1 new pass::" $tombpwd Err parazyd.org 70 i+ gen_key "$tombpwd" >> $TOMBKEYFILE Err parazyd.org 70 i+ } || { Err parazyd.org 70 i+ gen_key >> $TOMBKEYFILE Err parazyd.org 70 i+ } Err parazyd.org 70 i+ Err parazyd.org 70 i+ # load the key contents (set global variable) Err parazyd.org 70 i+ TOMBKEY="${mapfile[$TOMBKEYFILE]}" Err parazyd.org 70 i+ Err parazyd.org 70 i+ # this does a check on the file header Err parazyd.org 70 i+ is_valid_key $TOMBKEY || { Err parazyd.org 70 i+ _warning "The key does not seem to be valid." Err parazyd.org 70 i+ _warning "Dumping contents to screen:" Err parazyd.org 70 i+ print "${mapfile[$TOMBKEY]}" Err parazyd.org 70 i+ _warning "--" Err parazyd.org 70 i+ _sudo umount ${keytmp} Err parazyd.org 70 i+ rm -r $keytmp Err parazyd.org 70 i+ _failure "Operation aborted." Err parazyd.org 70 i+ } Err parazyd.org 70 i+ Err parazyd.org 70 i+ _message "Done forging ::1 key file::" $TOMBKEYFILE Err parazyd.org 70 i+ _success "Your key is ready:" Err parazyd.org 70 i+ ls -lh $TOMBKEYFILE Err parazyd.org 70 i+} Err parazyd.org 70 i+ Err parazyd.org 70 i+# Step three -- Lock tomb Err parazyd.org 70 i+# Err parazyd.org 70 i+# Synopsis: tomb_lock file.tomb file.tomb.key [-o cipher] Err parazyd.org 70 i+# Err parazyd.org 70 i+# Lock the given tomb with the given key file, in fact formatting the Err parazyd.org 70 i+# loopback volume as a LUKS device. Err parazyd.org 70 i+# Default cipher 'aes-xts-plain64:sha256'can be overridden with -o Err parazyd.org 70 i+lock_tomb_with_key() { Err parazyd.org 70 i+ # old default was aes-cbc-essiv:sha256 Err parazyd.org 70 i+ # Override with -o Err parazyd.org 70 i+ # for more alternatives refer to cryptsetup(8) Err parazyd.org 70 i+ local cipher="aes-xts-plain64:sha256" Err parazyd.org 70 i+ Err parazyd.org 70 i+ local tombpath="$1" # First argument is the path to the tomb Err parazyd.org 70 i+ Err parazyd.org 70 i+ [[ -n $tombpath ]] || { Err parazyd.org 70 i+ _warning "No tomb specified for locking." Err parazyd.org 70 i+ _warning "Usage: tomb lock file.tomb file.tomb.key" Err parazyd.org 70 i+ return 1 Err parazyd.org 70 i+ } Err parazyd.org 70 i+ Err parazyd.org 70 i+ _plot $tombpath Err parazyd.org 70 i+ Err parazyd.org 70 i+ _message "Commanded to lock tomb ::1 tomb file::" $TOMBFILE Err parazyd.org 70 i+ Err parazyd.org 70 i+ [[ -f $TOMBPATH ]] || { Err parazyd.org 70 i+ _failure "There is no tomb here. You have to dig it first." } Err parazyd.org 70 i+ Err parazyd.org 70 i+ _verbose "Tomb found: ::1 tomb path::" $TOMBPATH Err parazyd.org 70 i+ Err parazyd.org 70 i+ lo_mount $TOMBPATH Err parazyd.org 70 i+ nstloop=`lo_new` Err parazyd.org 70 i+ Err parazyd.org 70 i+ _verbose "Loop mounted on ::1 mount point::" $nstloop Err parazyd.org 70 i+ Err parazyd.org 70 i+ _message "Checking if the tomb is empty (we never step on somebody else's bones)." Err parazyd.org 70 i+ _sudo cryptsetup isLuks ${nstloop} Err parazyd.org 70 i+ if [ $? = 0 ]; then Err parazyd.org 70 i+ # is it a LUKS encrypted nest? then bail out and avoid reformatting it Err parazyd.org 70 i+ _warning "The tomb was already locked with another key." Err parazyd.org 70 i+ _failure "Operation aborted. I cannot lock an already locked tomb. Go dig a new one." Err parazyd.org 70 i+ else Err parazyd.org 70 i+ _message "Fine, this tomb seems empty." Err parazyd.org 70 i+ fi Err parazyd.org 70 i+ Err parazyd.org 70 i+ _load_key # Try loading key from option -k and set TOMBKEYFILE Err parazyd.org 70 i+ Err parazyd.org 70 i+ # the encryption cipher for a tomb can be set when locking using -c Err parazyd.org 70 i+ { option_is_set -o } && algopt="$(option_value -o)" Err parazyd.org 70 i+ [[ -n "$algopt" ]] && cipher=$algopt Err parazyd.org 70 i+ _message "Locking using cipher: ::1 cipher::" $cipher Err parazyd.org 70 i+ Err parazyd.org 70 i+ # get the pass from the user and check it Err parazyd.org 70 i+ if option_is_set --tomb-pwd; then Err parazyd.org 70 i+ tomb_pwd="`option_value --tomb-pwd`" Err parazyd.org 70 i+ _verbose "tomb-pwd = ::1 tomb pass::" $tomb_pwd Err parazyd.org 70 i+ ask_key_password "$tomb_pwd" Err parazyd.org 70 i+ else Err parazyd.org 70 i+ ask_key_password Err parazyd.org 70 i+ fi Err parazyd.org 70 i+ [[ $? == 0 ]] || _failure "No valid password supplied." Err parazyd.org 70 i+ Err parazyd.org 70 i+ _success "Locking ::1 tomb file:: with ::2 tomb key file::" $TOMBFILE $TOMBKEYFILE Err parazyd.org 70 i+ Err parazyd.org 70 i+ _message "Formatting Luks mapped device." Err parazyd.org 70 i+ _cryptsetup --batch-mode \ Err parazyd.org 70 i+ --cipher ${cipher} --key-size 256 --key-slot 0 \ Err parazyd.org 70 i+ luksFormat ${nstloop} Err parazyd.org 70 i+ [[ $? == 0 ]] || { Err parazyd.org 70 i+ _warning "cryptsetup luksFormat returned an error." Err parazyd.org 70 i+ _failure "Operation aborted." } Err parazyd.org 70 i+ Err parazyd.org 70 i+ _cryptsetup --cipher ${cipher} luksOpen ${nstloop} tomb.tmp Err parazyd.org 70 i+ [[ $? == 0 ]] || { Err parazyd.org 70 i+ _warning "cryptsetup luksOpen returned an error." Err parazyd.org 70 i+ _failure "Operation aborted." } Err parazyd.org 70 i+ Err parazyd.org 70 i+ _message "Formatting your Tomb with Ext3/Ext4 filesystem." Err parazyd.org 70 i+ _sudo mkfs.ext4 -q -F -j -L $TOMBNAME /dev/mapper/tomb.tmp Err parazyd.org 70 i+ Err parazyd.org 70 i+ [[ $? == 0 ]] || { Err parazyd.org 70 i+ _warning "Tomb format returned an error." Err parazyd.org 70 i+ _warning "Your tomb ::1 tomb file:: may be corrupted." $TOMBFILE } Err parazyd.org 70 i+ Err parazyd.org 70 i+ # Sync Err parazyd.org 70 i+ _sudo cryptsetup luksClose tomb.tmp Err parazyd.org 70 i+ Err parazyd.org 70 i+ _message "Done locking ::1 tomb name:: using Luks dm-crypt ::2 cipher::" $TOMBNAME $cipher Err parazyd.org 70 i+ _success "Your tomb is ready in ::1 tomb path:: and secured with key ::2 tomb key::" \ Err parazyd.org 70 i+ $TOMBPATH $TOMBKEYFILE Err parazyd.org 70 i+ Err parazyd.org 70 i+} Err parazyd.org 70 i+ Err parazyd.org 70 i+# This function changes the key that locks a tomb Err parazyd.org 70 i+change_tomb_key() { Err parazyd.org 70 i+ local tombkey="$1" # Path to the tomb's key file Err parazyd.org 70 i+ local tombpath="$2" # Path to the tomb Err parazyd.org 70 i+ Err parazyd.org 70 i+ _message "Commanded to reset key for tomb ::1 tomb path::" $tombpath Err parazyd.org 70 i+ Err parazyd.org 70 i+ [[ -z "$tombpath" ]] && { Err parazyd.org 70 i+ _warning "Command 'setkey' needs two arguments: the old key file and the tomb." Err parazyd.org 70 i+ _warning "I.e: tomb -k new.tomb.key old.tomb.key secret.tomb" Err parazyd.org 70 i+ _failure "Execution aborted." Err parazyd.org 70 i+ } Err parazyd.org 70 i+ Err parazyd.org 70 i+ _check_swap Err parazyd.org 70 i+ Err parazyd.org 70 i+ # this also calls _plot() Err parazyd.org 70 i+ is_valid_tomb $tombpath Err parazyd.org 70 i+ Err parazyd.org 70 i+ lo_mount $TOMBPATH Err parazyd.org 70 i+ nstloop=`lo_new` Err parazyd.org 70 i+ _sudo cryptsetup isLuks ${nstloop} Err parazyd.org 70 i+ # is it a LUKS encrypted nest? we check one more time Err parazyd.org 70 i+ [[ $? == 0 ]] || { Err parazyd.org 70 i+ _failure "Not a valid LUKS encrypted volume: ::1 volume::" $TOMBPATH } Err parazyd.org 70 i+ Err parazyd.org 70 i+ _load_key $tombkey # Try loading given key and set TOMBKEY and Err parazyd.org 70 i+ # TOMBKEYFILE Err parazyd.org 70 i+ local oldkey=$TOMBKEY Err parazyd.org 70 i+ local oldkeyfile=$TOMBKEYFILE Err parazyd.org 70 i+ Err parazyd.org 70 i+ # we have everything, prepare to mount Err parazyd.org 70 i+ _success "Changing lock on tomb ::1 tomb name::" $TOMBNAME Err parazyd.org 70 i+ _message "Old key: ::1 old key::" $oldkeyfile Err parazyd.org 70 i+ Err parazyd.org 70 i+ # render the mapper Err parazyd.org 70 i+ mapdate=`date +%s` Err parazyd.org 70 i+ # save date of mount in minutes since 1970 Err parazyd.org 70 i+ mapper="tomb.$TOMBNAME.$mapdate.$(basename $nstloop)" Err parazyd.org 70 i+ Err parazyd.org 70 i+ # load the old key Err parazyd.org 70 i+ if option_is_set --tomb-old-pwd; then Err parazyd.org 70 i+ tomb_old_pwd="`option_value --tomb-old-pwd`" Err parazyd.org 70 i+ _verbose "tomb-old-pwd = ::1 old pass::" $tomb_old_pwd Err parazyd.org 70 i+ ask_key_password "$tomb_old_pwd" Err parazyd.org 70 i+ else Err parazyd.org 70 i+ ask_key_password Err parazyd.org 70 i+ fi Err parazyd.org 70 i+ [[ $? == 0 ]] || { Err parazyd.org 70 i+ _failure "No valid password supplied for the old key." } Err parazyd.org 70 i+ old_secret=$TOMBSECRET Err parazyd.org 70 i+ Err parazyd.org 70 i+ # luksOpen the tomb (not really mounting, just on the loopback) Err parazyd.org 70 i+ print -R -n - "$old_secret" | _sudo cryptsetup --key-file - \ Err parazyd.org 70 i+ luksOpen ${nstloop} ${mapper} Err parazyd.org 70 i+ [[ $? == 0 ]] || _failure "Unexpected error in luksOpen." Err parazyd.org 70 i+ Err parazyd.org 70 i+ _load_key # Try loading new key from option -k and set TOMBKEYFILE Err parazyd.org 70 i+ Err parazyd.org 70 i+ _message "New key: ::1 key file::" $TOMBKEYFILE Err parazyd.org 70 i+ Err parazyd.org 70 i+ if option_is_set --tomb-pwd; then Err parazyd.org 70 i+ tomb_new_pwd="`option_value --tomb-pwd`" Err parazyd.org 70 i+ _verbose "tomb-pwd = ::1 tomb pass::" $tomb_new_pwd Err parazyd.org 70 i+ ask_key_password "$tomb_new_pwd" Err parazyd.org 70 i+ else Err parazyd.org 70 i+ ask_key_password Err parazyd.org 70 i+ fi Err parazyd.org 70 i+ [[ $? == 0 ]] || { Err parazyd.org 70 i+ _failure "No valid password supplied for the new key." } Err parazyd.org 70 i+ Err parazyd.org 70 i+ _tmp_create Err parazyd.org 70 i+ tmpnewkey=$TOMBTMP Err parazyd.org 70 i+ print -R -n - "$TOMBSECRET" >> $tmpnewkey Err parazyd.org 70 i+ Err parazyd.org 70 i+ print -R -n - "$old_secret" | _sudo cryptsetup --key-file - \ Err parazyd.org 70 i+ luksChangeKey "$nstloop" "$tmpnewkey" Err parazyd.org 70 i+ Err parazyd.org 70 i+ [[ $? == 0 ]] || _failure "Unexpected error in luksChangeKey." Err parazyd.org 70 i+ Err parazyd.org 70 i+ _sudo cryptsetup luksClose "${mapper}" || _failure "Unexpected error in luksClose." Err parazyd.org 70 i+ Err parazyd.org 70 i+ _success "Succesfully changed key for tomb: ::1 tomb file::" $TOMBFILE Err parazyd.org 70 i+ _message "The new key is: ::1 new key::" $TOMBKEYFILE Err parazyd.org 70 i+ Err parazyd.org 70 i+ return 0 Err parazyd.org 70 i+} Err parazyd.org 70 i+ Err parazyd.org 70 i+# }}} - Creation Err parazyd.org 70 i+ Err parazyd.org 70 i+# {{{ Open Err parazyd.org 70 i+ Err parazyd.org 70 i+# $1 = tombfile $2(optional) = mountpoint Err parazyd.org 70 i+mount_tomb() { Err parazyd.org 70 i+ local tombpath="$1" # First argument is the path to the tomb Err parazyd.org 70 i+ [[ -n "$tombpath" ]] || _failure "No tomb name specified for opening." Err parazyd.org 70 i+ Err parazyd.org 70 i+ _message "Commanded to open tomb ::1 tomb name::" $tombpath Err parazyd.org 70 i+ Err parazyd.org 70 i+ _check_swap Err parazyd.org 70 i+ Err parazyd.org 70 i+ # this also calls _plot() Err parazyd.org 70 i+ is_valid_tomb $tombpath Err parazyd.org 70 i+ Err parazyd.org 70 i+ _load_key # Try loading new key from option -k and set TOMBKEYFILE Err parazyd.org 70 i+ Err parazyd.org 70 i+ tombmount="$2" Err parazyd.org 70 i+ [[ "$tombmount" = "" ]] && { Err parazyd.org 70 i+ tombmount=/media/$TOMBNAME Err parazyd.org 70 i+ [[ -d /media ]] || { # no /media found, adopting /run/media/$USER (udisks2 compat) Err parazyd.org 70 i+ tombmount=/run/media/$_USER/$TOMBNAME Err parazyd.org 70 i+ } Err parazyd.org 70 i+ _message "Mountpoint not specified, using default: ::1 mount point::" $tombmount Err parazyd.org 70 i+ } Err parazyd.org 70 i+ Err parazyd.org 70 i+ _success "Opening ::1 tomb file:: on ::2 mount point::" $TOMBNAME $tombmount Err parazyd.org 70 i+ Err parazyd.org 70 i+ lo_mount $TOMBPATH Err parazyd.org 70 i+ nstloop=`lo_new` Err parazyd.org 70 i+ Err parazyd.org 70 i+ _sudo cryptsetup isLuks ${nstloop} || { Err parazyd.org 70 i+ # is it a LUKS encrypted nest? see cryptsetup(1) Err parazyd.org 70 i+ _failure "::1 tomb file:: is not a valid Luks encrypted storage file." $TOMBFILE } Err parazyd.org 70 i+ Err parazyd.org 70 i+ _message "This tomb is a valid LUKS encrypted device." Err parazyd.org 70 i+ Err parazyd.org 70 i+ luksdump="`_sudo cryptsetup luksDump ${nstloop}`" Err parazyd.org 70 i+ tombdump=(`print $luksdump | awk ' Err parazyd.org 70 i+ /^Cipher name/ {print $3} Err parazyd.org 70 i+ /^Cipher mode/ {print $3} Err parazyd.org 70 i+ /^Hash spec/ {print $3}'`) Err parazyd.org 70 i+ _message "Cipher is \"::1 cipher::\" mode \"::2 mode::\" hash \"::3 hash::\"" $tombdump[1] $tombdump[2] $tombdump[3] Err parazyd.org 70 i+ Err parazyd.org 70 i+ slotwarn=`print $luksdump | awk ' Err parazyd.org 70 i+ BEGIN { zero=0 } Err parazyd.org 70 i+ /^Key slot 0/ { zero=1 } Err parazyd.org 70 i+ /^Key slot.*ENABLED/ { if(zero==1) print "WARN" }'` Err parazyd.org 70 i+ [[ "$slotwarn" == "WARN" ]] && { Err parazyd.org 70 i+ _warning "Multiple key slots are enabled on this tomb. Beware: there can be a backdoor." } Err parazyd.org 70 i+ Err parazyd.org 70 i+ # save date of mount in minutes since 1970 Err parazyd.org 70 i+ mapdate=`date +%s` Err parazyd.org 70 i+ Err parazyd.org 70 i+ mapper="tomb.$TOMBNAME.$mapdate.$(basename $nstloop)" Err parazyd.org 70 i+ Err parazyd.org 70 i+ _verbose "dev mapper device: ::1 mapper::" $mapper Err parazyd.org 70 i+ _verbose "Tomb key: ::1 key file::" $TOMBKEYFILE Err parazyd.org 70 i+ Err parazyd.org 70 i+ # take the name only, strip extensions Err parazyd.org 70 i+ _verbose "Tomb name: ::1 tomb name:: (to be engraved)" $TOMBNAME Err parazyd.org 70 i+ Err parazyd.org 70 i+ { option_is_set --tomb-pwd } && { Err parazyd.org 70 i+ tomb_pwd="`option_value --tomb-pwd`" Err parazyd.org 70 i+ _verbose "tomb-pwd = ::1 tomb pass::" $tomb_pwd Err parazyd.org 70 i+ ask_key_password "$tomb_pwd" Err parazyd.org 70 i+ } || { Err parazyd.org 70 i+ ask_key_password Err parazyd.org 70 i+ } Err parazyd.org 70 i+ [[ $? == 0 ]] || _failure "No valid password supplied." Err parazyd.org 70 i+ Err parazyd.org 70 i+ _cryptsetup luksOpen ${nstloop} ${mapper} Err parazyd.org 70 i+ [[ $? = 0 ]] || { Err parazyd.org 70 i+ _failure "Failure mounting the encrypted file." } Err parazyd.org 70 i+ Err parazyd.org 70 i+ # preserve the loopdev after exit Err parazyd.org 70 i+ lo_preserve "$nstloop" Err parazyd.org 70 i+ Err parazyd.org 70 i+ # array: [ cipher, keysize, loopdevice ] Err parazyd.org 70 i+ tombstat=(`_sudo cryptsetup status ${mapper} | awk ' Err parazyd.org 70 i+ /cipher:/ {print $2} Err parazyd.org 70 i+ /keysize:/ {print $2} Err parazyd.org 70 i+ /device:/ {print $2}'`) Err parazyd.org 70 i+ _success "Success unlocking tomb ::1 tomb name::" $TOMBNAME Err parazyd.org 70 i+ _verbose "Key size is ::1 size:: for cipher ::2 cipher::" $tombstat[2] $tombstat[1] Err parazyd.org 70 i+ Err parazyd.org 70 i+ _message "Checking filesystem via ::1::" $tombstat[3] Err parazyd.org 70 i+ _sudo fsck -p -C0 /dev/mapper/${mapper} Err parazyd.org 70 i+ _verbose "Tomb engraved as ::1 tomb name::" $TOMBNAME Err parazyd.org 70 i+ _sudo tune2fs -L $TOMBNAME /dev/mapper/${mapper} > /dev/null Err parazyd.org 70 i+ Err parazyd.org 70 i+ # we need root from here on Err parazyd.org 70 i+ _sudo mkdir -p $tombmount Err parazyd.org 70 i+ Err parazyd.org 70 i+ # Default mount options are overridden with the -o switch Err parazyd.org 70 i+ { option_is_set -o } && { Err parazyd.org 70 i+ local oldmountopts=$MOUNTOPTS Err parazyd.org 70 i+ MOUNTOPTS="$(option_value -o)" } Err parazyd.org 70 i+ Err parazyd.org 70 i+ # TODO: safety check MOUNTOPTS Err parazyd.org 70 i+ # safe_mount_options && \ Err parazyd.org 70 i+ _sudo mount -o $MOUNTOPTS /dev/mapper/${mapper} ${tombmount} Err parazyd.org 70 i+ # Clean up if the mount failed Err parazyd.org 70 i+ [[ $? == 0 ]] || { Err parazyd.org 70 i+ _warning "Error mounting ::1 mapper:: on ::2 tombmount::" $mapper $tombmount Err parazyd.org 70 i+ [[ $oldmountopts != $MOUNTOPTS ]] && \ Err parazyd.org 70 i+ _warning "Are mount options '::1 mount options::' valid?" $MOUNTOPTS Err parazyd.org 70 i+ # TODO: move cleanup to _endgame() Err parazyd.org 70 i+ [[ -d $tombmount ]] && _sudo rmdir $tombmount Err parazyd.org 70 i+ [[ -e /dev/mapper/$mapper ]] && _sudo cryptsetup luksClose $mapper Err parazyd.org 70 i+ # The loop is taken care of in _endgame() Err parazyd.org 70 i+ _failure "Cannot mount ::1 tomb name::" $TOMBNAME Err parazyd.org 70 i+ } Err parazyd.org 70 i+ Err parazyd.org 70 i+ _sudo chown $UID:$GID ${tombmount} Err parazyd.org 70 i+ _sudo chmod 0711 ${tombmount} Err parazyd.org 70 i+ Err parazyd.org 70 i+ _success "Success opening ::1 tomb file:: on ::2 mount point::" $TOMBFILE $tombmount Err parazyd.org 70 i+ Err parazyd.org 70 i+ local tombtty tombhost tombuid tombuser Err parazyd.org 70 i+ Err parazyd.org 70 i+ # print out when it was opened the last time, by whom and where Err parazyd.org 70 i+ [[ -r ${tombmount}/.last ]] && { Err parazyd.org 70 i+ tombsince=$(_cat ${tombmount}/.last) Err parazyd.org 70 i+ tombsince=$(date --date=@$tombsince +%c) Err parazyd.org 70 i+ tombtty=$(_cat ${tombmount}/.tty) Err parazyd.org 70 i+ tombhost=$(_cat ${tombmount}/.host) Err parazyd.org 70 i+ tomblast=$(_cat ${tombmount}/.last) Err parazyd.org 70 i+ tombuid=$(_cat ${tombmount}/.uid | tr -d ' ') Err parazyd.org 70 i+ Err parazyd.org 70 i+ tombuser=$(getent passwd $tombuid) Err parazyd.org 70 i+ tombuser=${tombuser[(ws@:@)1]} Err parazyd.org 70 i+ Err parazyd.org 70 i+ _message "Last visit by ::1 user::(::2 tomb build::) from ::3 tty:: on ::4 host::" $tombuser $tombuid $tombtty $tombhost Err parazyd.org 70 i+ _message "on date ::1 date::" $tombsince Err parazyd.org 70 i+ } Err parazyd.org 70 i+ # write down the UID and TTY that opened the tomb Err parazyd.org 70 i+ rm -f ${tombmount}/.uid Err parazyd.org 70 i+ print $_UID > ${tombmount}/.uid Err parazyd.org 70 i+ rm -f ${tombmount}/.tty Err parazyd.org 70 i+ print $_TTY > ${tombmount}/.tty Err parazyd.org 70 i+ # also the hostname Err parazyd.org 70 i+ rm -f ${tombmount}/.host Err parazyd.org 70 i+ hostname > ${tombmount}/.host Err parazyd.org 70 i+ # and the "last time opened" information Err parazyd.org 70 i+ # in minutes since 1970, this is printed at next open Err parazyd.org 70 i+ rm -f ${tombmount}/.last Err parazyd.org 70 i+ date +%s > ${tombmount}/.last Err parazyd.org 70 i+ # human readable: date --date=@"`cat .last`" +%c Err parazyd.org 70 i+ Err parazyd.org 70 i+ Err parazyd.org 70 i+ # process bind-hooks (mount -o bind of directories) Err parazyd.org 70 i+ # and post-hooks (execute on open) Err parazyd.org 70 i+ { option_is_set -n } || { Err parazyd.org 70 i+ exec_safe_bind_hooks ${tombmount} Err parazyd.org 70 i+ exec_safe_post_hooks ${tombmount} open } Err parazyd.org 70 i+ Err parazyd.org 70 i+ return 0 Err parazyd.org 70 i+} Err parazyd.org 70 i+ Err parazyd.org 70 i+## HOOKS EXECUTION Err parazyd.org 70 i+# Err parazyd.org 70 i+# Execution of code inside a tomb may present a security risk, e.g., Err parazyd.org 70 i+# if the tomb is shared or compromised, an attacker could embed Err parazyd.org 70 i+# malicious code. When in doubt, open the tomb with the -n switch in Err parazyd.org 70 i+# order to skip this feature and verify the files mount-hooks and Err parazyd.org 70 i+# bind-hooks inside the tomb yourself before letting them run. Err parazyd.org 70 i+ Err parazyd.org 70 i+# Mount files and directories from the tomb to the current user's HOME. Err parazyd.org 70 i+# Err parazyd.org 70 i+# Synopsis: exec_safe_bind_hooks /path/to/mounted/tomb Err parazyd.org 70 i+# Err parazyd.org 70 i+# This can be a security risk if you share tombs with untrusted people. Err parazyd.org 70 i+# In that case, use the -n switch to turn off this feature. Err parazyd.org 70 i+exec_safe_bind_hooks() { Err parazyd.org 70 i+ local mnt="$1" # First argument is the mount point of the tomb Err parazyd.org 70 i+ Err parazyd.org 70 i+ # Default mount options are overridden with the -o switch Err parazyd.org 70 i+ [[ -n ${(k)OPTS[-o]} ]] && MOUNTOPTS=${OPTS[-o]} Err parazyd.org 70 i+ Err parazyd.org 70 i+ # No HOME set? Note: this should never happen again. Err parazyd.org 70 i+ [[ -z $HOME ]] && { Err parazyd.org 70 i+ _warning "How pitiful! A tomb, and no HOME." Err parazyd.org 70 i+ return 1 } Err parazyd.org 70 i+ Err parazyd.org 70 i+ [[ -z $mnt || ! -d $mnt ]] && { Err parazyd.org 70 i+ _warning "Cannot exec bind hooks without a mounted tomb." Err parazyd.org 70 i+ return 1 } Err parazyd.org 70 i+ Err parazyd.org 70 i+ [[ -r "$mnt/bind-hooks" ]] || { Err parazyd.org 70 i+ _verbose "bind-hooks not found in ::1 mount point::" $mnt Err parazyd.org 70 i+ return 1 } Err parazyd.org 70 i+ Err parazyd.org 70 i+ typeset -Al maps # Maps of files and directories to mount Err parazyd.org 70 i+ typeset -al mounted # Track already mounted files and directories Err parazyd.org 70 i+ Err parazyd.org 70 i+ # better parsing for bind hooks checks for two separated words on Err parazyd.org 70 i+ # each line, using zsh word separator array subscript Err parazyd.org 70 i+ _bindhooks="${mapfile[${mnt}/bind-hooks]}" Err parazyd.org 70 i+ for h in ${(f)_bindhooks}; do Err parazyd.org 70 i+ s="${h[(w)1]}" Err parazyd.org 70 i+ d="${h[(w)2]}" Err parazyd.org 70 i+ [[ "$s" = "" ]] && { _warning "bind-hooks file is broken"; return 1 } Err parazyd.org 70 i+ [[ "$d" = "" ]] && { _warning "bind-hooks file is broken"; return 1 } Err parazyd.org 70 i+ maps+=($s $d) Err parazyd.org 70 i+ _verbose "bind-hook found: $s -> $d" Err parazyd.org 70 i+ done Err parazyd.org 70 i+ unset _bindhooks Err parazyd.org 70 i+ Err parazyd.org 70 i+ for dir in ${(k)maps}; do Err parazyd.org 70 i+ [[ "${dir[1]}" == "/" || "${dir[1,2]}" == ".." ]] && { Err parazyd.org 70 i+ _warning "bind-hooks map format: local/to/tomb local/to/\$HOME" Err parazyd.org 70 i+ continue } Err parazyd.org 70 i+ Err parazyd.org 70 i+ [[ "${${maps[$dir]}[1]}" == "/" || "${${maps[$dir]}[1,2]}" == ".." ]] && { Err parazyd.org 70 i+ _warning "bind-hooks map format: local/to/tomb local/to/\$HOME. Rolling back" Err parazyd.org 70 i+ for dir in ${mounted}; do _sudo umount $dir; done Err parazyd.org 70 i+ return 1 } Err parazyd.org 70 i+ Err parazyd.org 70 i+ if [[ ! -r "$HOME/${maps[$dir]}" ]]; then Err parazyd.org 70 i+ _warning "bind-hook target not existent, skipping ::1 home::/::2 subdir::" $HOME ${maps[$dir]} Err parazyd.org 70 i+ elif [[ ! -r "$mnt/$dir" ]]; then Err parazyd.org 70 i+ _warning "bind-hook source not found in tomb, skipping ::1 mount point::/::2 subdir::" $mnt $dir Err parazyd.org 70 i+ else Err parazyd.org 70 i+ _sudo mount -o bind,$MOUNTOPTS $mnt/$dir $HOME/${maps[$dir]} \ Err parazyd.org 70 i+ && mounted+=("$HOME/${maps[$dir]}") Err parazyd.org 70 i+ fi Err parazyd.org 70 i+ done Err parazyd.org 70 i+} Err parazyd.org 70 i+ Err parazyd.org 70 i+# Execute automated actions configured in the tomb. Err parazyd.org 70 i+# Err parazyd.org 70 i+# Synopsis: exec_safe_post_hooks /path/to/mounted/tomb [open|close] Err parazyd.org 70 i+# Err parazyd.org 70 i+# If an executable file named 'post-hooks' is found inside the tomb, Err parazyd.org 70 i+# run it as a user. This might need a dialog for security on what is Err parazyd.org 70 i+# being run, however we expect you know well what is inside your tomb. Err parazyd.org 70 i+# If you're mounting an untrusted tomb, be safe and use the -n switch Err parazyd.org 70 i+# to verify what it would run if you let it. This feature opens the Err parazyd.org 70 i+# possibility to make encrypted executables. Err parazyd.org 70 i+exec_safe_post_hooks() { Err parazyd.org 70 i+ local mnt=$1 # First argument is where the tomb is mounted Err parazyd.org 70 i+ local act=$2 # Either 'open' or 'close' Err parazyd.org 70 i+ Err parazyd.org 70 i+ # Only run if post-hooks has the executable bit set Err parazyd.org 70 i+ [[ -x $mnt/post-hooks ]] || return Err parazyd.org 70 i+ Err parazyd.org 70 i+ # If the file starts with a shebang, run it. Err parazyd.org 70 i+ cat $mnt/post-hooks | head -n1 | grep '^#!\s*/' &> /dev/null Err parazyd.org 70 i+ [[ $? == 0 ]] && { Err parazyd.org 70 i+ _success "Post hooks found, executing as user ::1 user name::." $USERNAME Err parazyd.org 70 i+ $mnt/post-hooks $act $mnt Err parazyd.org 70 i+ } Err parazyd.org 70 i+} Err parazyd.org 70 i+ Err parazyd.org 70 i+# }}} - Tomb open Err parazyd.org 70 i+ Err parazyd.org 70 i+# {{{ List Err parazyd.org 70 i+ Err parazyd.org 70 i+# list all tombs mounted in a readable format Err parazyd.org 70 i+# $1 is optional, to specify a tomb Err parazyd.org 70 i+list_tombs() { Err parazyd.org 70 i+ Err parazyd.org 70 i+ local tombname tombmount tombfs tombfsopts tombloop Err parazyd.org 70 i+ local ts tombtot tombused tombavail tombpercent tombp tombsince Err parazyd.org 70 i+ local tombtty tombhost tombuid tombuser Err parazyd.org 70 i+ # list all open tombs Err parazyd.org 70 i+ mounted_tombs=(`list_tomb_mounts $1`) Err parazyd.org 70 i+ [[ ${#mounted_tombs} == 0 ]] && { Err parazyd.org 70 i+ _failure "I can't see any ::1 status:: tomb, may they all rest in peace." ${1:-open} } Err parazyd.org 70 i+ Err parazyd.org 70 i+ for t in ${mounted_tombs}; do Err parazyd.org 70 i+ mapper=`basename ${t[(ws:;:)1]}` Err parazyd.org 70 i+ tombname=${t[(ws:;:)5]} Err parazyd.org 70 i+ tombmount=${t[(ws:;:)2]} Err parazyd.org 70 i+ tombfs=${t[(ws:;:)3]} Err parazyd.org 70 i+ tombfsopts=${t[(ws:;:)4]} Err parazyd.org 70 i+ tombloop=${mapper[(ws:.:)4]} Err parazyd.org 70 i+ Err parazyd.org 70 i+ # calculate tomb size Err parazyd.org 70 i+ ts=`df -hP /dev/mapper/$mapper | Err parazyd.org 70 i+awk "/mapper/"' { print $2 ";" $3 ";" $4 ";" $5 }'` Err parazyd.org 70 i+ tombtot=${ts[(ws:;:)1]} Err parazyd.org 70 i+ tombused=${ts[(ws:;:)2]} Err parazyd.org 70 i+ tombavail=${ts[(ws:;:)3]} Err parazyd.org 70 i+ tombpercent=${ts[(ws:;:)4]} Err parazyd.org 70 i+ tombp=${tombpercent%%%} Err parazyd.org 70 i+ Err parazyd.org 70 i+ # obsolete way to get the last open date from /dev/mapper Err parazyd.org 70 i+ # which doesn't work when tomb filename contain dots Err parazyd.org 70 i+ # tombsince=`date --date=@${mapper[(ws:.:)3]} +%c` Err parazyd.org 70 i+ Err parazyd.org 70 i+ # find out who opens it from where Err parazyd.org 70 i+ [[ -r ${tombmount}/.tty ]] && { Err parazyd.org 70 i+ tombsince=$(_cat ${tombmount}/.last) Err parazyd.org 70 i+ tombsince=$(date --date=@$tombsince +%c) Err parazyd.org 70 i+ tombtty=$(_cat ${tombmount}/.tty) Err parazyd.org 70 i+ tombhost=$(_cat ${tombmount}/.host) Err parazyd.org 70 i+ tombuid=$(_cat ${tombmount}/.uid | tr -d ' ') Err parazyd.org 70 i+ Err parazyd.org 70 i+ tombuser=$(getent passwd $tombuid) Err parazyd.org 70 i+ tombuser=${tombuser[(ws@:@)1]} Err parazyd.org 70 i+ } Err parazyd.org 70 i+ Err parazyd.org 70 i+ { option_is_set --get-mountpoint } && { print $tombmount; continue } Err parazyd.org 70 i+ Err parazyd.org 70 i+ _message "::1 tombname:: open on ::2 tombmount:: using ::3 tombfsopts::" \ Err parazyd.org 70 i+ $tombname $tombmount $tombfsopts Err parazyd.org 70 i+ Err parazyd.org 70 i+ _verbose "::1 tombname:: /dev/::2 tombloop:: device mounted (detach with losetup -d)" $tombname $tombloop Err parazyd.org 70 i+ Err parazyd.org 70 i+ _message "::1 tombname:: open since ::2 tombsince::" $tombname $tombsince Err parazyd.org 70 i+ Err parazyd.org 70 i+ [[ -z "$tombtty" ]] || { Err parazyd.org 70 i+ _message "::1 tombname:: open by ::2 tombuser:: from ::3 tombtty:: on ::4 tombhost::" \ Err parazyd.org 70 i+ $tombname $tombuser $tombtty $tombhost Err parazyd.org 70 i+ } Err parazyd.org 70 i+ Err parazyd.org 70 i+ _message "::1 tombname:: size ::2 tombtot:: of which ::3 tombused:: (::5 tombpercent::%) is used: ::4 tombavail:: free " \ Err parazyd.org 70 i+ $tombname $tombtot $tombused $tombavail $tombpercent Err parazyd.org 70 i+ Err parazyd.org 70 i+ [[ ${tombp} -ge 90 ]] && { Err parazyd.org 70 i+ _warning "::1 tombname:: warning: your tomb is almost full!" $tombname Err parazyd.org 70 i+ } Err parazyd.org 70 i+ Err parazyd.org 70 i+ # Now check hooks Err parazyd.org 70 i+ mounted_hooks=(`list_tomb_binds $tombname $tombmount`) Err parazyd.org 70 i+ for h in ${mounted_hooks}; do Err parazyd.org 70 i+ _message "::1 tombname:: hooks ::2 hookname:: on ::3 hookdest::" \ Err parazyd.org 70 i+ $tombname "`basename ${h[(ws:;:)1]}`" ${h[(ws:;:)2]} Err parazyd.org 70 i+ done Err parazyd.org 70 i+ done Err parazyd.org 70 i+} Err parazyd.org 70 i+ Err parazyd.org 70 i+ Err parazyd.org 70 i+# Print out an array of mounted tombs (internal use) Err parazyd.org 70 i+# Format is semi-colon separated list of attributes Err parazyd.org 70 i+# if 1st arg is supplied, then list only that tomb Err parazyd.org 70 i+# Err parazyd.org 70 i+# String positions in the semicolon separated array: Err parazyd.org 70 i+# Err parazyd.org 70 i+# 1. full mapper path Err parazyd.org 70 i+# Err parazyd.org 70 i+# 2. mountpoint Err parazyd.org 70 i+# Err parazyd.org 70 i+# 3. filesystem type Err parazyd.org 70 i+# Err parazyd.org 70 i+# 4. mount options Err parazyd.org 70 i+# Err parazyd.org 70 i+# 5. tomb name Err parazyd.org 70 i+list_tomb_mounts() { Err parazyd.org 70 i+ [[ -z "$1" ]] && { Err parazyd.org 70 i+ # list all open tombs Err parazyd.org 70 i+ mount -l \ Err parazyd.org 70 i+ | awk ' Err parazyd.org 70 i+BEGIN { main="" } Err parazyd.org 70 i+/^\/dev\/mapper\/tomb/ { Err parazyd.org 70 i+ if(main==$1) next; Err parazyd.org 70 i+ print $1 ";" $3 ";" $5 ";" $6 ";" $7 Err parazyd.org 70 i+ main=$1 Err parazyd.org 70 i+} Err parazyd.org 70 i+' Err parazyd.org 70 i+ } || { Err parazyd.org 70 i+ # list a specific tomb Err parazyd.org 70 i+ mount -l \ Err parazyd.org 70 i+ | awk -vtomb="[$1]" ' Err parazyd.org 70 i+BEGIN { main="" } Err parazyd.org 70 i+/^\/dev\/mapper\/tomb/ { Err parazyd.org 70 i+ if($7!=tomb) next; Err parazyd.org 70 i+ if(main==$1) next; Err parazyd.org 70 i+ print $1 ";" $3 ";" $5 ";" $6 ";" $7 Err parazyd.org 70 i+ main=$1 Err parazyd.org 70 i+} Err parazyd.org 70 i+' Err parazyd.org 70 i+ } Err parazyd.org 70 i+} Err parazyd.org 70 i+ Err parazyd.org 70 i+# list_tomb_binds Err parazyd.org 70 i+# print out an array of mounted bind hooks (internal use) Err parazyd.org 70 i+# format is semi-colon separated list of attributes Err parazyd.org 70 i+# needs two arguments: name of tomb whose hooks belong Err parazyd.org 70 i+# mount tomb Err parazyd.org 70 i+list_tomb_binds() { Err parazyd.org 70 i+ [[ -z "$2" ]] && { Err parazyd.org 70 i+ _failure "Internal error: list_tomb_binds called without argument." } Err parazyd.org 70 i+ Err parazyd.org 70 i+ # OK well, prepare for some insanity: parsing the mount table on GNU/Linux Err parazyd.org 70 i+ # is like combing a Wookie while he is riding a speedbike down a valley. Err parazyd.org 70 i+ Err parazyd.org 70 i+ typeset -A tombs Err parazyd.org 70 i+ typeset -a binds Err parazyd.org 70 i+ for t in "${(f)$(mount -l | grep '/dev/mapper/tomb.*]$')}"; do Err parazyd.org 70 i+ len="${(w)#t}" Err parazyd.org 70 i+ [[ "${t[(w)$len]}" = "$1" ]] || continue Err parazyd.org 70 i+ tombs+=( ${t[(w)1]} ${t[(w)$len]} ) Err parazyd.org 70 i+ Err parazyd.org 70 i+ done Err parazyd.org 70 i+ Err parazyd.org 70 i+ for m in ${(k)tombs}; do Err parazyd.org 70 i+ for p in "${(f)$(cat /proc/mounts):s/\\040(deleted)/}"; do Err parazyd.org 70 i+ # Debian's kernel appends a '\040(deleted)' to the mountpoint in /proc/mounts Err parazyd.org 70 i+ # so if we parse the string as-is then this will break the parsing. How nice of them! Err parazyd.org 70 i+ # Some bugs related to this are more than 10yrs old. Such Debian! Much stable! Very parsing! Err parazyd.org 70 i+ # Bug #711183 umount parser for /proc/mounts broken on stale nfs mount (gets renamed to "/mnt/point (deleted)") Err parazyd.org 70 i+ # Bug #711184 mount should not stat mountpoints on mount Err parazyd.org 70 i+ # Bug #711187 linux-image-3.2.0-4-amd64: kernel should not rename mountpoint if nfs server is dead/unreachable Err parazyd.org 70 i+ [[ "${p[(w)1]}" = "$m" ]] && { Err parazyd.org 70 i+ [[ "${(q)p[(w)2]}" != "${(q)2}" ]] && { Err parazyd.org 70 i+ # Our output format: Err parazyd.org 70 i+ # mapper;mountpoint;fs;flags;name Err parazyd.org 70 i+ binds+=("$m;${(q)p[(w)2]};${p[(w)3]};${p[(w)4]};${tombs[$m]}") } Err parazyd.org 70 i+ } Err parazyd.org 70 i+ done Err parazyd.org 70 i+ done Err parazyd.org 70 i+ Err parazyd.org 70 i+ # print the results out line by line Err parazyd.org 70 i+ for b in $binds; do print - "$b"; done Err parazyd.org 70 i+} Err parazyd.org 70 i+ Err parazyd.org 70 i+# }}} - Tomb list Err parazyd.org 70 i+ Err parazyd.org 70 i+# {{{ Index and search Err parazyd.org 70 i+ Err parazyd.org 70 i+# index files in all tombs for search Err parazyd.org 70 i+# $1 is optional, to specify a tomb Err parazyd.org 70 i+index_tombs() { Err parazyd.org 70 i+ { command -v updatedb 1>/dev/null 2>/dev/null } || { Err parazyd.org 70 i+ _failure "Cannot index tombs on this system: updatedb (mlocate) not installed." } Err parazyd.org 70 i+ Err parazyd.org 70 i+ updatedbver=`updatedb --version | grep '^updatedb'` Err parazyd.org 70 i+ [[ "$updatedbver" =~ "GNU findutils" ]] && { Err parazyd.org 70 i+ _warning "Cannot use GNU findutils for index/search commands." } Err parazyd.org 70 i+ [[ "$updatedbver" =~ "mlocate" ]] || { Err parazyd.org 70 i+ _failure "Index command needs 'mlocate' to be installed." } Err parazyd.org 70 i+ Err parazyd.org 70 i+ _verbose "$updatedbver" Err parazyd.org 70 i+ Err parazyd.org 70 i+ mounted_tombs=(`list_tomb_mounts $1`) Err parazyd.org 70 i+ [[ ${#mounted_tombs} == 0 ]] && { Err parazyd.org 70 i+ # Considering one tomb Err parazyd.org 70 i+ [[ -n "$1" ]] && { Err parazyd.org 70 i+ _failure "There seems to be no open tomb engraved as [::1::]" $1 } Err parazyd.org 70 i+ # Or more Err parazyd.org 70 i+ _failure "I can't see any open tomb, may they all rest in peace." } Err parazyd.org 70 i+ Err parazyd.org 70 i+ _success "Creating and updating search indexes." Err parazyd.org 70 i+ Err parazyd.org 70 i+ # start the LibreOffice document converter if installed Err parazyd.org 70 i+ { command -v unoconv 1>/dev/null 2>/dev/null } && { Err parazyd.org 70 i+ unoconv -l 2>/dev/null & Err parazyd.org 70 i+ _verbose "unoconv listener launched." Err parazyd.org 70 i+ sleep 1 } Err parazyd.org 70 i+ Err parazyd.org 70 i+ for t in ${mounted_tombs}; do Err parazyd.org 70 i+ mapper=`basename ${t[(ws:;:)1]}` Err parazyd.org 70 i+ tombname=${t[(ws:;:)5]} Err parazyd.org 70 i+ tombmount=${t[(ws:;:)2]} Err parazyd.org 70 i+ [[ -r ${tombmount}/.noindex ]] && { Err parazyd.org 70 i+ _message "Skipping ::1 tomb name:: (.noindex found)." $tombname Err parazyd.org 70 i+ continue } Err parazyd.org 70 i+ _message "Indexing ::1 tomb name:: filenames..." $tombname Err parazyd.org 70 i+ updatedb -l 0 -o ${tombmount}/.updatedb -U ${tombmount} Err parazyd.org 70 i+ Err parazyd.org 70 i+ # here we use swish to index file contents Err parazyd.org 70 i+ [[ $SWISH == 1 ]] && { Err parazyd.org 70 i+ _message "Indexing ::1 tomb name:: contents..." $tombname Err parazyd.org 70 i+ rm -f ${tombmount}/.swishrc Err parazyd.org 70 i+ _message "Generating a new swish-e configuration file: ::1 swish conf::" ${tombmount}/.swishrc Err parazyd.org 70 i+ cat < ${tombmount}/.swishrc Err parazyd.org 70 i+# index directives Err parazyd.org 70 i+DefaultContents TXT* Err parazyd.org 70 i+IndexDir $tombmount Err parazyd.org 70 i+IndexFile $tombmount/.swish Err parazyd.org 70 i+# exclude images Err parazyd.org 70 i+FileRules filename regex /\.jp.?g/i Err parazyd.org 70 i+FileRules filename regex /\.png/i Err parazyd.org 70 i+FileRules filename regex /\.gif/i Err parazyd.org 70 i+FileRules filename regex /\.tiff/i Err parazyd.org 70 i+FileRules filename regex /\.svg/i Err parazyd.org 70 i+FileRules filename regex /\.xcf/i Err parazyd.org 70 i+FileRules filename regex /\.eps/i Err parazyd.org 70 i+FileRules filename regex /\.ttf/i Err parazyd.org 70 i+# exclude audio Err parazyd.org 70 i+FileRules filename regex /\.mp3/i Err parazyd.org 70 i+FileRules filename regex /\.ogg/i Err parazyd.org 70 i+FileRules filename regex /\.wav/i Err parazyd.org 70 i+FileRules filename regex /\.mod/i Err parazyd.org 70 i+FileRules filename regex /\.xm/i Err parazyd.org 70 i+# exclude video Err parazyd.org 70 i+FileRules filename regex /\.mp4/i Err parazyd.org 70 i+FileRules filename regex /\.avi/i Err parazyd.org 70 i+FileRules filename regex /\.ogv/i Err parazyd.org 70 i+FileRules filename regex /\.ogm/i Err parazyd.org 70 i+FileRules filename regex /\.mkv/i Err parazyd.org 70 i+FileRules filename regex /\.mov/i Err parazyd.org 70 i+FileRules filename regex /\.flv/i Err parazyd.org 70 i+FileRules filename regex /\.webm/i Err parazyd.org 70 i+# exclude system Err parazyd.org 70 i+FileRules filename is ok Err parazyd.org 70 i+FileRules filename is lock Err parazyd.org 70 i+FileRules filename is control Err parazyd.org 70 i+FileRules filename is status Err parazyd.org 70 i+FileRules filename is proc Err parazyd.org 70 i+FileRules filename is sys Err parazyd.org 70 i+FileRules filename is supervise Err parazyd.org 70 i+FileRules filename regex /\.asc$/i Err parazyd.org 70 i+FileRules filename regex /\.gpg$/i Err parazyd.org 70 i+# pdf and postscript Err parazyd.org 70 i+FileFilter .pdf pdftotext "'%p' -" Err parazyd.org 70 i+FileFilter .ps ps2txt "'%p' -" Err parazyd.org 70 i+# compressed files Err parazyd.org 70 i+FileFilterMatch lesspipe "%p" /\.tgz$/i Err parazyd.org 70 i+FileFilterMatch lesspipe "%p" /\.zip$/i Err parazyd.org 70 i+FileFilterMatch lesspipe "%p" /\.gz$/i Err parazyd.org 70 i+FileFilterMatch lesspipe "%p" /\.bz2$/i Err parazyd.org 70 i+FileFilterMatch lesspipe "%p" /\.Z$/ Err parazyd.org 70 i+# spreadsheets Err parazyd.org 70 i+FileFilterMatch unoconv "-d spreadsheet -f csv --stdout %P" /\.xls.*/i Err parazyd.org 70 i+FileFilterMatch unoconv "-d spreadsheet -f csv --stdout %P" /\.xlt.*/i Err parazyd.org 70 i+FileFilter .ods unoconv "-d spreadsheet -f csv --stdout %P" Err parazyd.org 70 i+FileFilter .ots unoconv "-d spreadsheet -f csv --stdout %P" Err parazyd.org 70 i+FileFilter .dbf unoconv "-d spreadsheet -f csv --stdout %P" Err parazyd.org 70 i+FileFilter .dif unoconv "-d spreadsheet -f csv --stdout %P" Err parazyd.org 70 i+FileFilter .uos unoconv "-d spreadsheet -f csv --stdout %P" Err parazyd.org 70 i+FileFilter .sxc unoconv "-d spreadsheet -f csv --stdout %P" Err parazyd.org 70 i+# word documents Err parazyd.org 70 i+FileFilterMatch unoconv "-d document -f txt --stdout %P" /\.doc.*/i Err parazyd.org 70 i+FileFilterMatch unoconv "-d document -f txt --stdout %P" /\.odt.*/i Err parazyd.org 70 i+FileFilterMatch unoconv "-d document -f txt --stdout %P" /\.rtf.*/i Err parazyd.org 70 i+FileFilterMatch unoconv "-d document -f txt --stdout %P" /\.tex$/i Err parazyd.org 70 i+# native html support Err parazyd.org 70 i+IndexContents HTML* .htm .html .shtml Err parazyd.org 70 i+IndexContents XML* .xml Err parazyd.org 70 i+EOF Err parazyd.org 70 i+ Err parazyd.org 70 i+ swish-e -c ${tombmount}/.swishrc -S fs -v3 Err parazyd.org 70 i+ } Err parazyd.org 70 i+ _message "Search index updated." Err parazyd.org 70 i+ done Err parazyd.org 70 i+} Err parazyd.org 70 i+ Err parazyd.org 70 i+search_tombs() { Err parazyd.org 70 i+ { command -v locate 1>/dev/null 2>/dev/null } || { Err parazyd.org 70 i+ _failure "Cannot index tombs on this system: updatedb (mlocate) not installed." } Err parazyd.org 70 i+ Err parazyd.org 70 i+ updatedbver=`updatedb --version | grep '^updatedb'` Err parazyd.org 70 i+ [[ "$updatedbver" =~ "GNU findutils" ]] && { Err parazyd.org 70 i+ _warning "Cannot use GNU findutils for index/search commands." } Err parazyd.org 70 i+ [[ "$updatedbver" =~ "mlocate" ]] || { Err parazyd.org 70 i+ _failure "Index command needs 'mlocate' to be installed." } Err parazyd.org 70 i+ Err parazyd.org 70 i+ _verbose "$updatedbver" Err parazyd.org 70 i+ Err parazyd.org 70 i+ # list all open tombs Err parazyd.org 70 i+ mounted_tombs=(`list_tomb_mounts`) Err parazyd.org 70 i+ [[ ${#mounted_tombs} == 0 ]] && { Err parazyd.org 70 i+ _failure "I can't see any open tomb, may they all rest in peace." } Err parazyd.org 70 i+ Err parazyd.org 70 i+ _success "Searching for: ::1::" ${(f)@} Err parazyd.org 70 i+ for t in ${mounted_tombs}; do Err parazyd.org 70 i+ _verbose "Checking for index: ::1::" ${t} Err parazyd.org 70 i+ mapper=`basename ${t[(ws:;:)1]}` Err parazyd.org 70 i+ tombname=${t[(ws:;:)5]} Err parazyd.org 70 i+ tombmount=${t[(ws:;:)2]} Err parazyd.org 70 i+ [[ -r ${tombmount}/.updatedb ]] && { Err parazyd.org 70 i+ # Use mlocate to search hits on filenames Err parazyd.org 70 i+ _message "Searching filenames in tomb ::1 tomb name::" $tombname Err parazyd.org 70 i+ locate -d ${tombmount}/.updatedb -e -i "${(f)@}" Err parazyd.org 70 i+ _message "Matches found: ::1 matches::" \ Err parazyd.org 70 i+ $(locate -d ${tombmount}/.updatedb -e -i -c ${(f)@}) Err parazyd.org 70 i+ Err parazyd.org 70 i+ # Use swish-e to search over contents Err parazyd.org 70 i+ [[ $SWISH == 1 && -r $tombmount/.swish ]] && { Err parazyd.org 70 i+ _message "Searching contents in tomb ::1 tomb name::" $tombname Err parazyd.org 70 i+ swish-e -w ${=@} -f $tombmount/.swish -H0 } Err parazyd.org 70 i+ } || { Err parazyd.org 70 i+ _warning "Skipping tomb ::1 tomb name::: not indexed." $tombname Err parazyd.org 70 i+ _warning "Run 'tomb index' to create indexes." } Err parazyd.org 70 i+ done Err parazyd.org 70 i+ _message "Search completed." Err parazyd.org 70 i+} Err parazyd.org 70 i+ Err parazyd.org 70 i+# }}} - Index and search Err parazyd.org 70 i+ Err parazyd.org 70 i+# {{{ Resize Err parazyd.org 70 i+ Err parazyd.org 70 i+# resize tomb file size Err parazyd.org 70 i+resize_tomb() { Err parazyd.org 70 i+ local tombpath="$1" # First argument is the path to the tomb Err parazyd.org 70 i+ Err parazyd.org 70 i+ _message "Commanded to resize tomb ::1 tomb name:: to ::2 size:: mebibytes." $1 $OPTS[-s] Err parazyd.org 70 i+ Err parazyd.org 70 i+ [[ -z "$tombpath" ]] && _failure "No tomb name specified for resizing." Err parazyd.org 70 i+ [[ ! -r $tombpath ]] && _failure "Cannot find ::1::" $tombpath Err parazyd.org 70 i+ Err parazyd.org 70 i+ newtombsize="`option_value -s`" Err parazyd.org 70 i+ [[ -z "$newtombsize" ]] && { Err parazyd.org 70 i+ _failure "Aborting operations: new size was not specified, use -s" } Err parazyd.org 70 i+ Err parazyd.org 70 i+ # this also calls _plot() Err parazyd.org 70 i+ is_valid_tomb $tombpath Err parazyd.org 70 i+ Err parazyd.org 70 i+ _load_key # Try loading new key from option -k and set TOMBKEYFILE Err parazyd.org 70 i+ Err parazyd.org 70 i+ local oldtombsize=$(( `stat -c %s "$TOMBPATH" 2>/dev/null` / 1048576 )) Err parazyd.org 70 i+ local mounted_tomb=`mount -l | Err parazyd.org 70 i+ awk -vtomb="[$TOMBNAME]" '/^\/dev\/mapper\/tomb/ { if($7==tomb) print $1 }'` Err parazyd.org 70 i+ Err parazyd.org 70 i+ # Tomb must not be open Err parazyd.org 70 i+ [[ -z "$mounted_tomb" ]] || { Err parazyd.org 70 i+ _failure "Please close the tomb ::1 tomb name:: before trying to resize it." $TOMBNAME } Err parazyd.org 70 i+ # New tomb size must be specified Err parazyd.org 70 i+ [[ -n "$newtombsize" ]] || { Err parazyd.org 70 i+ _failure "You must specify the new size of ::1 tomb name::" $TOMBNAME } Err parazyd.org 70 i+ # New tomb size must be an integer Err parazyd.org 70 i+ [[ $newtombsize == <-> ]] || _failure "Size is not an integer." Err parazyd.org 70 i+ Err parazyd.org 70 i+ # Tombs can only grow in size Err parazyd.org 70 i+ if [[ "$newtombsize" -gt "$oldtombsize" ]]; then Err parazyd.org 70 i+ Err parazyd.org 70 i+ delta="$(( $newtombsize - $oldtombsize ))" Err parazyd.org 70 i+ Err parazyd.org 70 i+ _message "Generating ::1 tomb file:: of ::2 size::MiB" $TOMBFILE $newtombsize Err parazyd.org 70 i+ Err parazyd.org 70 i+ _verbose "Data dump using ::1:: from /dev/urandom" ${DD[1]} Err parazyd.org 70 i+ ${=DD} if=/dev/urandom bs=1048576 count=${delta} >> $TOMBPATH Err parazyd.org 70 i+ [[ $? == 0 ]] || { Err parazyd.org 70 i+ _failure "Error creating the extra resize ::1 size::, operation aborted." \ Err parazyd.org 70 i+ $tmp_resize } Err parazyd.org 70 i+ Err parazyd.org 70 i+ # If same size this allows to re-launch resize if pinentry expires Err parazyd.org 70 i+ # so that it will continue resizing without appending more space. Err parazyd.org 70 i+ # Resizing the partition to the file size cannot harm data anyway. Err parazyd.org 70 i+ elif [[ "$newtombsize" = "$oldtombsize" ]]; then Err parazyd.org 70 i+ _message "Tomb seems resized already, operating filesystem stretch" Err parazyd.org 70 i+ else Err parazyd.org 70 i+ _failure "The new size must be greater then old tomb size." Err parazyd.org 70 i+ fi Err parazyd.org 70 i+ Err parazyd.org 70 i+ { option_is_set --tomb-pwd } && { Err parazyd.org 70 i+ tomb_pwd="`option_value --tomb-pwd`" Err parazyd.org 70 i+ _verbose "tomb-pwd = ::1 tomb pass::" $tomb_pwd Err parazyd.org 70 i+ ask_key_password "$tomb_pwd" Err parazyd.org 70 i+ } || { Err parazyd.org 70 i+ ask_key_password Err parazyd.org 70 i+ } Err parazyd.org 70 i+ [[ $? == 0 ]] || _failure "No valid password supplied." Err parazyd.org 70 i+ Err parazyd.org 70 i+ lo_mount "$TOMBPATH" Err parazyd.org 70 i+ nstloop=`lo_new` Err parazyd.org 70 i+ Err parazyd.org 70 i+ mapdate=`date +%s` Err parazyd.org 70 i+ mapper="tomb.$TOMBNAME.$mapdate.$(basename $nstloop)" Err parazyd.org 70 i+ Err parazyd.org 70 i+ _message "opening tomb" Err parazyd.org 70 i+ _cryptsetup luksOpen ${nstloop} ${mapper} || { Err parazyd.org 70 i+ _failure "Failure mounting the encrypted file." } Err parazyd.org 70 i+ Err parazyd.org 70 i+ _sudo cryptsetup resize "${mapper}" || { Err parazyd.org 70 i+ _failure "cryptsetup failed to resize ::1 mapper::" $mapper } Err parazyd.org 70 i+ Err parazyd.org 70 i+ _sudo e2fsck -p -f /dev/mapper/${mapper} || { Err parazyd.org 70 i+ _failure "e2fsck failed to check ::1 mapper::" $mapper } Err parazyd.org 70 i+ Err parazyd.org 70 i+ _sudo resize2fs /dev/mapper/${mapper} || { Err parazyd.org 70 i+ _failure "resize2fs failed to resize ::1 mapper::" $mapper } Err parazyd.org 70 i+ Err parazyd.org 70 i+ # close and free the loop device Err parazyd.org 70 i+ _sudo cryptsetup luksClose "${mapper}" Err parazyd.org 70 i+ Err parazyd.org 70 i+ return 0 Err parazyd.org 70 i+} Err parazyd.org 70 i+ Err parazyd.org 70 i+# }}} Err parazyd.org 70 i+ Err parazyd.org 70 i+# {{{ Close Err parazyd.org 70 i+ Err parazyd.org 70 i+umount_tomb() { Err parazyd.org 70 i+ local tombs how_many_tombs Err parazyd.org 70 i+ local pathmap mapper tombname tombmount loopdev Err parazyd.org 70 i+ local ans pidk pname Err parazyd.org 70 i+ Err parazyd.org 70 i+ if [ "$1" = "all" ]; then Err parazyd.org 70 i+ mounted_tombs=(`list_tomb_mounts`) Err parazyd.org 70 i+ else Err parazyd.org 70 i+ mounted_tombs=(`list_tomb_mounts $1`) Err parazyd.org 70 i+ fi Err parazyd.org 70 i+ Err parazyd.org 70 i+ [[ ${#mounted_tombs} == 0 ]] && { Err parazyd.org 70 i+ _failure "There is no open tomb to be closed." } Err parazyd.org 70 i+ Err parazyd.org 70 i+ [[ ${#mounted_tombs} -gt 1 && -z "$1" ]] && { Err parazyd.org 70 i+ _warning "Too many tombs mounted, please specify one (see tomb list)" Err parazyd.org 70 i+ _warning "or issue the command 'tomb close all' to close them all." Err parazyd.org 70 i+ _failure "Operation aborted." } Err parazyd.org 70 i+ Err parazyd.org 70 i+ for t in ${mounted_tombs}; do Err parazyd.org 70 i+ mapper=`basename ${t[(ws:;:)1]}` Err parazyd.org 70 i+ Err parazyd.org 70 i+ # strip square parens from tombname Err parazyd.org 70 i+ tombname=${t[(ws:;:)5]} Err parazyd.org 70 i+ tombmount=${t[(ws:;:)2]} Err parazyd.org 70 i+ tombfs=${t[(ws:;:)3]} Err parazyd.org 70 i+ tombfsopts=${t[(ws:;:)4]} Err parazyd.org 70 i+ tombloop=${mapper[(ws:.:)4]} Err parazyd.org 70 i+ Err parazyd.org 70 i+ _verbose "Name: ::1 tomb name::" $tombname Err parazyd.org 70 i+ _verbose "Mount: ::1 mount point::" $tombmount Err parazyd.org 70 i+ _verbose "Mapper: ::1 mapper::" $mapper Err parazyd.org 70 i+ Err parazyd.org 70 i+ [[ -e "$mapper" ]] && { Err parazyd.org 70 i+ _warning "Tomb not found: ::1 tomb file::" $1 Err parazyd.org 70 i+ _warning "Please specify an existing tomb." Err parazyd.org 70 i+ return 0 } Err parazyd.org 70 i+ Err parazyd.org 70 i+ [[ -n $SLAM ]] && { Err parazyd.org 70 i+ _success "Slamming tomb ::1 tomb name:: mounted on ::2 mount point::" \ Err parazyd.org 70 i+ $tombname $tombmount Err parazyd.org 70 i+ _message "Kill all processes busy inside the tomb." Err parazyd.org 70 i+ { slam_tomb "$tombmount" } || { Err parazyd.org 70 i+ _failure "Cannot slam the tomb ::1 tomb name::" $tombname } Err parazyd.org 70 i+ } || { Err parazyd.org 70 i+ _message "Closing tomb ::1 tomb name:: mounted on ::2 mount point::" \ Err parazyd.org 70 i+ $tombname $tombmount } Err parazyd.org 70 i+ Err parazyd.org 70 i+ # check if there are binded dirs and close them Err parazyd.org 70 i+ bind_tombs=(`list_tomb_binds $tombname $tombmount`) Err parazyd.org 70 i+ for b in ${bind_tombs}; do Err parazyd.org 70 i+ bind_mapper="${b[(ws:;:)1]}" Err parazyd.org 70 i+ bind_mount="${b[(ws:;:)2]}" Err parazyd.org 70 i+ _message "Closing tomb bind hook: ::1 hook::" $bind_mount Err parazyd.org 70 i+ _sudo umount "`print - ${bind_mount}`" || { Err parazyd.org 70 i+ [[ -n $SLAM ]] && { Err parazyd.org 70 i+ _success "Slamming tomb: killing all processes using this hook." Err parazyd.org 70 i+ slam_tomb "`print - ${bind_mount}`" || _failure "Cannot slam the bind hook ::1 hook::" $bind_mount Err parazyd.org 70 i+ umount "`print - ${bind_mount}`" || _failure "Cannot slam the bind hook ::1 hook::" $bind_mount Err parazyd.org 70 i+ } || { Err parazyd.org 70 i+ _failure "Tomb bind hook ::1 hook:: is busy, cannot close tomb." $bind_mount Err parazyd.org 70 i+ } Err parazyd.org 70 i+ } Err parazyd.org 70 i+ done Err parazyd.org 70 i+ Err parazyd.org 70 i+ # Execute post-hooks for eventual cleanup Err parazyd.org 70 i+ { option_is_set -n } || { Err parazyd.org 70 i+ exec_safe_post_hooks ${tombmount%%/} close } Err parazyd.org 70 i+ Err parazyd.org 70 i+ _verbose "Performing umount of ::1 mount point::" $tombmount Err parazyd.org 70 i+ _sudo umount ${tombmount} Err parazyd.org 70 i+ [[ $? = 0 ]] || { _failure "Tomb is busy, cannot umount!" } Err parazyd.org 70 i+ Err parazyd.org 70 i+ # If we used a default mountpoint and is now empty, delete it Err parazyd.org 70 i+ tombname_regex=${tombname//\[/} Err parazyd.org 70 i+ tombname_regex=${tombname_regex//\]/} Err parazyd.org 70 i+ Err parazyd.org 70 i+ [[ "$tombmount" -regex-match "[/run]?/media[/$_USER]?/$tombname_regex" ]] && { Err parazyd.org 70 i+ _sudo rmdir $tombmount } Err parazyd.org 70 i+ Err parazyd.org 70 i+ _sudo cryptsetup luksClose $mapper Err parazyd.org 70 i+ [[ $? == 0 ]] || { Err parazyd.org 70 i+ _failure "Error occurred in cryptsetup luksClose ::1 mapper::" $mapper } Err parazyd.org 70 i+ Err parazyd.org 70 i+ # Normally the loopback device is detached when unused Err parazyd.org 70 i+ [[ -e "/dev/$tombloop" ]] && _sudo losetup -d "/dev/$tombloop" Err parazyd.org 70 i+ [[ $? = 0 ]] || { Err parazyd.org 70 i+ _verbose "/dev/$tombloop was already closed." } Err parazyd.org 70 i+ Err parazyd.org 70 i+ _success "Tomb ::1 tomb name:: closed: your bones will rest in peace." $tombname Err parazyd.org 70 i+ Err parazyd.org 70 i+ done # loop across mounted tombs Err parazyd.org 70 i+ Err parazyd.org 70 i+ return 0 Err parazyd.org 70 i+} Err parazyd.org 70 i+ Err parazyd.org 70 i+# Kill all processes using the tomb Err parazyd.org 70 i+slam_tomb() { Err parazyd.org 70 i+ # $1 = tomb mount point Err parazyd.org 70 i+ if [[ -z `fuser -m "$1" 2>/dev/null` ]]; then Err parazyd.org 70 i+ return 0 Err parazyd.org 70 i+ fi Err parazyd.org 70 i+ #Note: shells are NOT killed by INT or TERM, but they are killed by HUP Err parazyd.org 70 i+ for s in TERM HUP KILL; do Err parazyd.org 70 i+ _verbose "Sending ::1:: to processes inside the tomb:" $s Err parazyd.org 70 i+ if option_is_set -D; then Err parazyd.org 70 i+ ps -fp `fuser -m /media/a.tomb 2>/dev/null`| Err parazyd.org 70 i+ while read line; do Err parazyd.org 70 i+ _verbose $line Err parazyd.org 70 i+ done Err parazyd.org 70 i+ fi Err parazyd.org 70 i+ fuser -s -m "$1" -k -M -$s Err parazyd.org 70 i+ if [[ -z `fuser -m "$1" 2>/dev/null` ]]; then Err parazyd.org 70 i+ return 0 Err parazyd.org 70 i+ fi Err parazyd.org 70 i+ if ! option_is_set -f; then Err parazyd.org 70 i+ sleep 3 Err parazyd.org 70 i+ fi Err parazyd.org 70 i+ done Err parazyd.org 70 i+ return 1 Err parazyd.org 70 i+} Err parazyd.org 70 i+ Err parazyd.org 70 i+# }}} - Tomb close Err parazyd.org 70 i+ Err parazyd.org 70 i+# {{{ Main routine Err parazyd.org 70 i+ Err parazyd.org 70 i+main() { Err parazyd.org 70 i+ Err parazyd.org 70 i+ _ensure_dependencies # Check dependencies are present or bail out Err parazyd.org 70 i+ Err parazyd.org 70 i+ local -A subcommands_opts Err parazyd.org 70 i+ ### Options configuration Err parazyd.org 70 i+ # Err parazyd.org 70 i+ # Hi, dear developer! Are you trying to add a new subcommand, or Err parazyd.org 70 i+ # to add some options? Well, keep in mind that option names are Err parazyd.org 70 i+ # global: they cannot bear a different meaning or behaviour across Err parazyd.org 70 i+ # subcommands. The only exception is "-o" which means: "options Err parazyd.org 70 i+ # passed to the local subcommand", and thus can bear a different Err parazyd.org 70 i+ # meaning for different subcommands. Err parazyd.org 70 i+ # Err parazyd.org 70 i+ # For example, "-s" means "size" and accepts one argument. If you Err parazyd.org 70 i+ # are tempted to add an alternate option "-s" (e.g., to mean Err parazyd.org 70 i+ # "silent", and that doesn't accept any argument) DON'T DO IT! Err parazyd.org 70 i+ # Err parazyd.org 70 i+ # There are two reasons for that: Err parazyd.org 70 i+ # I. Usability; users expect that "-s" is "size" Err parazyd.org 70 i+ # II. Option parsing WILL EXPLODE if you do this kind of bad Err parazyd.org 70 i+ # things (it will complain: "option defined more than once") Err parazyd.org 70 i+ # Err parazyd.org 70 i+ # If you want to use the same option in multiple commands then you Err parazyd.org 70 i+ # can only use the non-abbreviated long-option version like: Err parazyd.org 70 i+ # -force and NOT -f Err parazyd.org 70 i+ # Err parazyd.org 70 i+ main_opts=(q -quiet=q D -debug=D h -help=h v -version=v f -force=f -tmp: U: G: T: -no-color -unsafe) Err parazyd.org 70 i+ subcommands_opts[__default]="" Err parazyd.org 70 i+ # -o in open and mount is used to pass alternate mount options Err parazyd.org 70 i+ subcommands_opts[open]="n -nohook=n k: -kdf: o: -ignore-swap -tomb-pwd: " Err parazyd.org 70 i+ subcommands_opts[mount]=${subcommands_opts[open]} Err parazyd.org 70 i+ Err parazyd.org 70 i+ subcommands_opts[create]="" # deprecated, will issue warning Err parazyd.org 70 i+ Err parazyd.org 70 i+ # -o in forge and lock is used to pass an alternate cipher. Err parazyd.org 70 i+ subcommands_opts[forge]="-ignore-swap k: -kdf: o: -tomb-pwd: -use-urandom " Err parazyd.org 70 i+ subcommands_opts[dig]="-ignore-swap s: -size=s " Err parazyd.org 70 i+ subcommands_opts[lock]="-ignore-swap k: -kdf: o: -tomb-pwd: " Err parazyd.org 70 i+ subcommands_opts[setkey]="k: -ignore-swap -kdf: -tomb-old-pwd: -tomb-pwd: " Err parazyd.org 70 i+ subcommands_opts[engrave]="k: " Err parazyd.org 70 i+ Err parazyd.org 70 i+ subcommands_opts[passwd]="k: -ignore-swap -kdf: -tomb-old-pwd: -tomb-pwd: " Err parazyd.org 70 i+ subcommands_opts[close]="" Err parazyd.org 70 i+ subcommands_opts[help]="" Err parazyd.org 70 i+ subcommands_opts[slam]="" Err parazyd.org 70 i+ subcommands_opts[list]="-get-mountpoint " Err parazyd.org 70 i+ Err parazyd.org 70 i+ subcommands_opts[index]="" Err parazyd.org 70 i+ subcommands_opts[search]="" Err parazyd.org 70 i+ Err parazyd.org 70 i+ subcommands_opts[help]="" Err parazyd.org 70 i+ subcommands_opts[bury]="k: -tomb-pwd: " Err parazyd.org 70 i+ subcommands_opts[exhume]="k: -tomb-pwd: " Err parazyd.org 70 i+ # subcommands_opts[decompose]="" Err parazyd.org 70 i+ # subcommands_opts[recompose]="" Err parazyd.org 70 i+ # subcommands_opts[install]="" Err parazyd.org 70 i+ subcommands_opts[askpass]="" Err parazyd.org 70 i+ subcommands_opts[source]="" Err parazyd.org 70 i+ subcommands_opts[resize]="-ignore-swap s: -size=s k: -tomb-pwd: " Err parazyd.org 70 i+ subcommands_opts[check]="-ignore-swap " Err parazyd.org 70 i+ # subcommands_opts[translate]="" Err parazyd.org 70 i+ Err parazyd.org 70 i+ ### Detect subcommand Err parazyd.org 70 i+ local -aU every_opts #every_opts behave like a set; that is, an array with unique elements Err parazyd.org 70 i+ for optspec in $subcommands_opts$main_opts; do Err parazyd.org 70 i+ for opt in ${=optspec}; do Err parazyd.org 70 i+ every_opts+=${opt} Err parazyd.org 70 i+ done Err parazyd.org 70 i+ done Err parazyd.org 70 i+ local -a oldstar Err parazyd.org 70 i+ oldstar=("${(@)argv}") Err parazyd.org 70 i+ #### detect early: useful for --option-parsing Err parazyd.org 70 i+ zparseopts -M -D -Adiscardme ${every_opts} Err parazyd.org 70 i+ if [[ -n ${(k)discardme[--option-parsing]} ]]; then Err parazyd.org 70 i+ print $1 Err parazyd.org 70 i+ if [[ -n "$1" ]]; then Err parazyd.org 70 i+ return 1 Err parazyd.org 70 i+ fi Err parazyd.org 70 i+ return 0 Err parazyd.org 70 i+ fi Err parazyd.org 70 i+ unset discardme Err parazyd.org 70 i+ if ! zparseopts -M -E -D -Adiscardme ${every_opts}; then Err parazyd.org 70 i+ _failure "Error parsing." Err parazyd.org 70 i+ return 127 Err parazyd.org 70 i+ fi Err parazyd.org 70 i+ unset discardme Err parazyd.org 70 i+ subcommand=$1 Err parazyd.org 70 i+ if [[ -z $subcommand ]]; then Err parazyd.org 70 i+ subcommand="__default" Err parazyd.org 70 i+ fi Err parazyd.org 70 i+ Err parazyd.org 70 i+ if [[ -z ${(k)subcommands_opts[$subcommand]} ]]; then Err parazyd.org 70 i+ _warning "There's no such command \"::1 subcommand::\"." $subcommand Err parazyd.org 70 i+ exitv=127 _failure "Please try -h for help." Err parazyd.org 70 i+ fi Err parazyd.org 70 i+ argv=("${(@)oldstar}") Err parazyd.org 70 i+ unset oldstar Err parazyd.org 70 i+ Err parazyd.org 70 i+ ### Parsing global + command-specific options Err parazyd.org 70 i+ # zsh magic: ${=string} will split to multiple arguments when spaces occur Err parazyd.org 70 i+ set -A cmd_opts ${main_opts} ${=subcommands_opts[$subcommand]} Err parazyd.org 70 i+ # if there is no option, we don't need parsing Err parazyd.org 70 i+ if [[ -n $cmd_opts ]]; then Err parazyd.org 70 i+ zparseopts -M -E -D -AOPTS ${cmd_opts} Err parazyd.org 70 i+ if [[ $? != 0 ]]; then Err parazyd.org 70 i+ _warning "Some error occurred during option processing." Err parazyd.org 70 i+ exitv=127 _failure "See \"tomb help\" for more info." Err parazyd.org 70 i+ fi Err parazyd.org 70 i+ fi Err parazyd.org 70 i+ #build PARAM (array of arguments) and check if there are unrecognized options Err parazyd.org 70 i+ ok=0 Err parazyd.org 70 i+ PARAM=() Err parazyd.org 70 i+ for arg in $*; do Err parazyd.org 70 i+ if [[ $arg == '--' || $arg == '-' ]]; then Err parazyd.org 70 i+ ok=1 Err parazyd.org 70 i+ continue #it shouldn't be appended to PARAM Err parazyd.org 70 i+ elif [[ $arg[1] == '-' ]]; then Err parazyd.org 70 i+ if [[ $ok == 0 ]]; then Err parazyd.org 70 i+ exitv=127 _failure "Unrecognized option ::1 arg:: for subcommand ::2 subcommand::" $arg $subcommand Err parazyd.org 70 i+ fi Err parazyd.org 70 i+ fi Err parazyd.org 70 i+ PARAM+=$arg Err parazyd.org 70 i+ done Err parazyd.org 70 i+ # First parameter actually is the subcommand: delete it and shift Err parazyd.org 70 i+ [[ $subcommand != '__default' ]] && { PARAM[1]=(); shift } Err parazyd.org 70 i+ Err parazyd.org 70 i+ ### End parsing command-specific options Err parazyd.org 70 i+ Err parazyd.org 70 i+ # Use colors unless told not to Err parazyd.org 70 i+ { ! option_is_set --no-color } && { autoload -Uz colors && colors } Err parazyd.org 70 i+ # Some options are only available during insecure mode Err parazyd.org 70 i+ { ! option_is_set --unsafe } && { Err parazyd.org 70 i+ for opt in --tomb-pwd --use-urandom --tomb-old-pwd; do Err parazyd.org 70 i+ { option_is_set $opt } && { Err parazyd.org 70 i+ exitv=127 _failure "You specified option ::1 option::, which is DANGEROUS and should only be used for testing\nIf you really want so, add --unsafe" $opt } Err parazyd.org 70 i+ done Err parazyd.org 70 i+ } Err parazyd.org 70 i+ # read -t or --tmp flags to set a custom temporary directory Err parazyd.org 70 i+ option_is_set --tmp && TMPPREFIX=$(option_value --tmp) Err parazyd.org 70 i+ Err parazyd.org 70 i+ Err parazyd.org 70 i+ # When we run as root, we remember the original uid:gid to set Err parazyd.org 70 i+ # permissions for the calling user and drop privileges Err parazyd.org 70 i+ _whoami # Reset _UID, _GID, _TTY Err parazyd.org 70 i+ Err parazyd.org 70 i+ [[ "$PARAM" == "" ]] && { Err parazyd.org 70 i+ _verbose "Tomb command: ::1 subcommand::" $subcommand Err parazyd.org 70 i+ } || { Err parazyd.org 70 i+ _verbose "Tomb command: ::1 subcommand:: ::2 param::" $subcommand $PARAM Err parazyd.org 70 i+ } Err parazyd.org 70 i+ Err parazyd.org 70 i+ [[ -z $_UID ]] || { Err parazyd.org 70 i+ _verbose "Caller: uid[::1 uid::], gid[::2 gid::], tty[::3 tty::]." \ Err parazyd.org 70 i+ $_UID $_GID $_TTY Err parazyd.org 70 i+ } Err parazyd.org 70 i+ Err parazyd.org 70 i+ _verbose "Temporary directory: $TMPPREFIX" Err parazyd.org 70 i+ Err parazyd.org 70 i+ # Process subcommand Err parazyd.org 70 i+ case "$subcommand" in Err parazyd.org 70 i+ Err parazyd.org 70 i+ # USAGE Err parazyd.org 70 i+ help) Err parazyd.org 70 i+ usage Err parazyd.org 70 i+ ;; Err parazyd.org 70 i+ Err parazyd.org 70 i+ # DEPRECATION notice (leave here as 'create' is still present in old docs) Err parazyd.org 70 i+ create) Err parazyd.org 70 i+ _warning "The create command is deprecated, please use dig, forge and lock instead." Err parazyd.org 70 i+ _warning "For more informations see Tomb's manual page (man tomb)." Err parazyd.org 70 i+ _failure "Operation aborted." Err parazyd.org 70 i+ ;; Err parazyd.org 70 i+ Err parazyd.org 70 i+ # CREATE Step 1: dig -s NN file.tomb Err parazyd.org 70 i+ dig) Err parazyd.org 70 i+ dig_tomb ${=PARAM} Err parazyd.org 70 i+ ;; Err parazyd.org 70 i+ Err parazyd.org 70 i+ # CREATE Step 2: forge file.tomb.key Err parazyd.org 70 i+ forge) Err parazyd.org 70 i+ forge_key ${=PARAM} Err parazyd.org 70 i+ ;; Err parazyd.org 70 i+ Err parazyd.org 70 i+ # CREATE Step 2: lock -k file.tomb.key file.tomb Err parazyd.org 70 i+ lock) Err parazyd.org 70 i+ lock_tomb_with_key ${=PARAM} Err parazyd.org 70 i+ ;; Err parazyd.org 70 i+ Err parazyd.org 70 i+ # Open the tomb Err parazyd.org 70 i+ mount|open) Err parazyd.org 70 i+ mount_tomb ${=PARAM} Err parazyd.org 70 i+ ;; Err parazyd.org 70 i+ Err parazyd.org 70 i+ # Close the tomb Err parazyd.org 70 i+ # `slam` is used to force closing. Err parazyd.org 70 i+ umount|close|slam) Err parazyd.org 70 i+ [[ "$subcommand" == "slam" ]] && SLAM=1 Err parazyd.org 70 i+ umount_tomb $PARAM[1] Err parazyd.org 70 i+ ;; Err parazyd.org 70 i+ Err parazyd.org 70 i+ # Grow tomb's size Err parazyd.org 70 i+ resize) Err parazyd.org 70 i+ [[ $RESIZER == 0 ]] && { Err parazyd.org 70 i+ _failure "Resize2fs not installed: cannot resize tombs." } Err parazyd.org 70 i+ resize_tomb $PARAM[1] Err parazyd.org 70 i+ ;; Err parazyd.org 70 i+ Err parazyd.org 70 i+ ## Contents manipulation Err parazyd.org 70 i+ Err parazyd.org 70 i+ # Index tomb contents Err parazyd.org 70 i+ index) Err parazyd.org 70 i+ index_tombs $PARAM[1] Err parazyd.org 70 i+ ;; Err parazyd.org 70 i+ Err parazyd.org 70 i+ # List tombs Err parazyd.org 70 i+ list) Err parazyd.org 70 i+ list_tombs $PARAM[1] Err parazyd.org 70 i+ ;; Err parazyd.org 70 i+ Err parazyd.org 70 i+ # Search tomb contents Err parazyd.org 70 i+ search) Err parazyd.org 70 i+ search_tombs ${=PARAM} Err parazyd.org 70 i+ ;; Err parazyd.org 70 i+ Err parazyd.org 70 i+ ## Locking operations Err parazyd.org 70 i+ Err parazyd.org 70 i+ # Export key to QR Code Err parazyd.org 70 i+ engrave) Err parazyd.org 70 i+ [[ $QRENCODE == 0 ]] && { Err parazyd.org 70 i+ _failure "QREncode not installed: cannot engrave keys on paper." } Err parazyd.org 70 i+ engrave_key ${=PARAM} Err parazyd.org 70 i+ ;; Err parazyd.org 70 i+ Err parazyd.org 70 i+ # Change password on existing key Err parazyd.org 70 i+ passwd) Err parazyd.org 70 i+ change_passwd $PARAM[1] Err parazyd.org 70 i+ ;; Err parazyd.org 70 i+ Err parazyd.org 70 i+ # Change tomb key Err parazyd.org 70 i+ setkey) Err parazyd.org 70 i+ change_tomb_key ${=PARAM} Err parazyd.org 70 i+ ;; Err parazyd.org 70 i+ Err parazyd.org 70 i+ # STEGANOGRAPHY: hide key inside an image Err parazyd.org 70 i+ bury) Err parazyd.org 70 i+ [[ $STEGHIDE == 0 ]] && { Err parazyd.org 70 i+ _failure "Steghide not installed: cannot bury keys into images." } Err parazyd.org 70 i+ bury_key $PARAM[1] Err parazyd.org 70 i+ ;; Err parazyd.org 70 i+ Err parazyd.org 70 i+ # STEGANOGRAPHY: read key hidden in an image Err parazyd.org 70 i+ exhume) Err parazyd.org 70 i+ [[ $STEGHIDE == 0 ]] && { Err parazyd.org 70 i+ _failure "Steghide not installed: cannot exhume keys from images." } Err parazyd.org 70 i+ exhume_key $PARAM[1] Err parazyd.org 70 i+ ;; Err parazyd.org 70 i+ Err parazyd.org 70 i+ ## Internal commands useful to developers Err parazyd.org 70 i+ Err parazyd.org 70 i+ # Make tomb functions available to the calling shell or script Err parazyd.org 70 i+ 'source') return 0 ;; Err parazyd.org 70 i+ Err parazyd.org 70 i+ # Ask user for a password interactively Err parazyd.org 70 i+ askpass) ask_password $PARAM[1] $PARAM[2] ;; Err parazyd.org 70 i+ Err parazyd.org 70 i+ # Default operation: presentation, or version information with -v Err parazyd.org 70 i+ __default) Err parazyd.org 70 i+ _print "Tomb ::1 version:: - a strong and gentle undertaker for your secrets" $VERSION Err parazyd.org 70 i+ _print "\000" Err parazyd.org 70 i+ _print " Copyright (C) 2007-2015 Dyne.org Foundation, License GNU GPL v3+" Err parazyd.org 70 i+ _print " This is free software: you are free to change and redistribute it" Err parazyd.org 70 i+ _print " For the latest sourcecode go to " Err parazyd.org 70 i+ _print "\000" Err parazyd.org 70 i+ option_is_set -v && { Err parazyd.org 70 i+ local langwas=$LANG Err parazyd.org 70 i+ LANG=en Err parazyd.org 70 i+ _print " This source code is distributed in the hope that it will be useful," Err parazyd.org 70 i+ _print " but WITHOUT ANY WARRANTY; without even the implied warranty of" Err parazyd.org 70 i+ _print " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." Err parazyd.org 70 i+ LANG=$langwas Err parazyd.org 70 i+ _print " When in need please refer to ." Err parazyd.org 70 i+ _print "\000" Err parazyd.org 70 i+ _print "System utils:" Err parazyd.org 70 i+ _print "\000" Err parazyd.org 70 i+ cat <