HOWTO: create a GELI password/data safe

Introduction
I've seen friends use Password Safe to store all their many passwords that one typically creates these days, and I decided to put something simple together using FreeBSD's GELI encrypted storage module that I could use for passwords and other bits of simple data.

Description
So it works like this: create a md(4) device, initialise geli on it, put a file system on it, and mount it into your home dir. Once mounted you can put any kind of data in the directory you need, or structure your own password storage design - it could be as simple as a text file for each password, or as elaborate as a SQLite database for all your passwords, or anything else you can conjure up. I've written a small shell script to make mounting and unmounting easy, and which you can extend to do easy password storage/retrieval. At the end of the day your safe will be stored in a single file in your home directory which you can backup or copy to other systems.

Setup
Setting up GELI has been covered many times, but for completeness I'll cover it again here. Feel free to read geli(8) if you want to delve deeper into it.

First we're going to create a sparse file that will be our md vnode backend. I'm creating a 100 MB file, but feel free to go bigger or smaller. Thanks to sparse files, the space is only consumed when data is actually written to the file through use over time, not when it is generated with dd:

Code:
dd if=/dev/zero of=gelisafe.md bs=1k seek=100k count=0

To increase/decrease the size, increase/decrease the seek or bs parameters above. Do not touch the count parameter.

Now create the md device:

Code:
mdconfig -a -t vnode -f /usr/home/aragon/gelisafe.md

That command will output the md device name, for example "md0". This will be our GELI provider, so let's now initialise GELI on it:

Code:
geli init /dev/md0

Enter a passphrase to use for encrypting/decrypting your data.

Now attach and newfs your GELI device:

Code:
geli attach md0 && newfs -U -O 1 -f 512 -b 4096 -i 8192 /dev/md0.eli

If all went well you should be able to mount it somewhere. I mount it in my home directory. Be sure to first create the directory where you want it mounted.

Code:
mount /dev/md0.eli /usr/home/aragon/gelisafe

Now would be a good time to setup permissions/ownership in that filesystem, then umount and detach the GELI device:

Code:
chown aragon:staff /usr/home/aragon/gelisafe
umount /usr/home/aragon/gelisafe
geli dettach md0

If all went well there, go ahead and install security/sudo and add this to your sudoers file using the visudo command:

Code:
aragon  ALL=(ALL) NOPASSWD: /usr/home/aragon/bin/safe.sh

Of course, you would need to replace "aragon" with your own username.

Now create ~/bin/safe.sh and paste this into it:

Code:
#!/bin/sh

cleanup () {
	rm -f ${TMPFILE}
}

SAFEMD=/usr/home/aragon/gelisafe.md
SAFEMOUNT=/usr/home/aragon/gelisafe

case "$1" in
mount|umount)
	sudo ${0} _${1}
	;;
_mount)
	TMPFILE=$( mktemp -t safe ) || exit 1
	trap cleanup 1 3 5 15 EXIT
	mdconfig -l -v >${TMPFILE}
	while read MDDEV MDTYPE MDSIZE MDPATH; do
		if [ "${MDPATH}" = "${SAFEMD}" ]; then
			geli status >${TMPFILE} || exit 1
			while read GDEV GSTATUS GPROV; do
				if [ "${GPROV}" = "${MDDEV}" ]; then
					ATTACHED=1
					break 2
				fi
			done <${TMPFILE}
			geli attach -d ${MDDEV} || exit 1
			ATTACHED=1
			break
		fi
	done <${TMPFILE}
	if [ ! ${ATTACHED} ]; then
		MDDEV="$( mdconfig -a -t vnode -f ${SAFEMD} )" || exit 1
		geli attach -d ${MDDEV} || exit 1
	fi
	mount |grep -q ^/dev/${MDDEV}.eli && echo already mounted && exit 0
	mount /dev/${MDDEV}.eli ${SAFEMOUNT}
	;;
_umount)
	umount ${SAFEMOUNT} || exit 1
	;;
genpass)
	dd if=/dev/random bs=64k count=1 2>/dev/null |md5
	;;
*)
	echo "$0: <mount|umount>" 1>&2
	exit 1
	;;
esac

Before saving ~/bin/safe.sh, edit the SAFEMD and SAFEMOUNT variables near the top. Set them to the full path of your md vnode backend and where you want your safe mounted respectively.

Use
To mount and unmount your safe you should be able to run the following without root permissions:

Code:
safe.sh mount
safe.sh umount

If those don't work, you might need to add ~/bin to your PATH.

As a minor bonus I wrote in a simple password generator too:

Code:
safe.sh genpass

Once the safe is mounted, it is up to you to put data into it. The script doesn't do any of that for you. For example, if you want to store passwords in it you could just create one text file for each password using the file name as a password identifier. That's all up to you. Feel free to extend safe.sh yourself if you want to add automated password storage/retrieval functions, or whatever else you desire.

Whenever you're done using your safe, don't forget to unmount it.
 
Back
Top