Creating user-mountable encrypted devices
There are already some ways to create securely encrypted devices within the linux kernel (described in LaptopSicherEinrichten [German]). But the mount command only supports the old loop device method which is considered obsolete and does not work with packet writing to DVD-RW and similar.
Here is a script which implement a dmcrypt filesystem type for mount which make these things possible.
I say fsck!
mount helpers are run in user context, not as root, which is good, but the options we need to make this work need root privileges so we rely on sudo. The good point of this is that we can define much finer access rules with that (mount by group membership, etc), the bad side is, that the script should be much more carefull than it currently is:
The script just 'works' but is not yet secured against shell escapes and other possible attacks
Add the following to your /etc/sudoers file:
# users and %groups who might use dmcrypt mount helpers User_Alias DMCRYPT = %disk, %fuse, %floppy # definition, our both helpers can be called without supplying a password to become root DMCRYPT ALL=NOPASSWD: /sbin/mount.dmcrypt, /sbin/umount.dmcrypt
example /etc/fstab entry
important is that the mount device becomes a mapped blockdevice and you must supply a dm=blockdevice option to tell the real device to use.
#MAPPED_DEVICE MOUNTPOINT FS OPTIONS /dev/mapper/dvdrw /media/cryptdvdrw dmcrypt dm=/dev/pktcdvd/dvdrw,rw,user,noauto,noatime 0 0
Mount helper script
store this as /sbin/mount.dmcrypt and hardlink it as /sbin/umount.dmcrypt too. Take care that this file is owned by root:root and not writeable by users, it sudo's itself, no suid-bit needed.
#!/bin/bash
#
# dmcrypt mount helper
# Christian Thaeter <chth@gmx.net>
# based on FUSE mount helper by
# Petr Klima <qaxi@seznam.cz>
# Thanks to Miklos Szeredi <miklos@szeredi.hu>
# to kick me to the right way
#
function die {
echo -e "$PRGNAME# $1" >&2
[ -z "$2" ] && exit 128
exit "$2"
}
head -1 /proc/$PPID/maps | {
read z z z z z MNT
[ $MNT = '/bin/mount' -o $MNT = '/bin/umount' ] || die "$0 must be called by /bin/mount or /bin/umount"
}
[ $UID != 0 ] && DMCRYPT_USER=$USER exec sudo $0 $@
DMCRYPT_USER=${SUDO_USER:-$USER}
case $0 in
/sbin/mount.dmcrypt)
MOUNTPATH="$1"
MOUNTPOINT="$2"
[ -b "${MOUNTPATH}" ] && die "Directory ${MOUNTPATH} already mapped"
[ -d "${MOUNTPOINT}" ] || die "Directory ${MOUNTPOINT} does not exist"
shift 3
DMDEV="${MOUNTPATH##*/}"
CSOPTS=''
# process dm=
MOUNTPATH=$(echo "$*" | sed -e 's/.*dm=\([^,]*\)/\1/')
OPTS=$(echo "$*" | sed -e 's/\(.*\)dm=[^,]*\(.*\)/\1\2/g;s/\(.*\),/\1/')
# process ro
expr "$OPTS" : ro >/dev/null && CSOPTS='-r'
[ -b "${MOUNTPATH}" ] || die "Directory ${MOUNTPATH} is not a block device"
# TODO: handle mount options:
# encryption=cipher
# keybits=bits
# keyfd keyfile keyagent
# eject auto-eject on umount
/sbin/cryptsetup create $CSOPTS "$DMDEV" "$MOUNTPATH" || die "cryptsetup failure"
/bin/mount -t auto /dev/mapper/$DMDEV $MOUNTPOINT -n -o $OPTS || {
/sbin/cryptsetup remove "$DMDEV"
die "mount failure"
}
echo "/dev/mapper/$DMDEV $MOUNTPOINT dmcrypt $@,user=$DMCRYPT_USER 0 0" >>/etc/mtab
;;
/sbin/umount.dmcrypt)
UMOUNTPATH="$1"
grep " $UMOUNTPATH dmcrypt " /etc/mtab | {
read MOUNTPATH MOUNTPOINT dmcrypt OPTS z z
DMDEV="${MOUNTPATH##*/}"
umount -ni "$MOUNTPOINT"
/sbin/cryptsetup remove "$DMDEV"
mv /etc/mtab /etc/mtab~
grep -v "^$MOUNTPATH $MOUNTPOINT dmcrypt " </etc/mtab~ >/etc/mtab
rm /etc/mtab~
}
;;
esac
mount.dmcrypt If you're using the LuKS-Extension of cryptsetup, you have to use a slightly different helper script:
#!/bin/bash
#
# dmcrypt mount helper
# Christian Thaeter <chth@gmx.net>
# based on FUSE mount helper by
# Petr Klima <qaxi@seznam.cz>
# Thanks to Miklos Szeredi <miklos@szeredi.hu>
# to kick me to the right way
#
function die {
echo -e "$PRGNAME# $1" >&2
[ -z "$2" ] && exit 128
exit "$2"
}
head -1 /proc/$PPID/maps | {
read z z z z z MNT
[ $MNT = '/bin/mount' -o $MNT = '/bin/umount' ] || die "$0 must be called by /bin/mount or /bin/umount"
}
[ $UID != 0 ] && DMCRYPT_USER=$USER exec sudo $0 $@
DMCRYPT_USER=${SUDO_USER:-$USER}
case $0 in
/sbin/mount.dmcrypt)
MOUNTPATH="$1"
MOUNTPOINT="$2"
[ -b "${MOUNTPATH}" ] && die "Directory ${MOUNTPATH} already mapped"
[ -d "${MOUNTPOINT}" ] || die "Directory ${MOUNTPOINT} does not exist"
shift 3
DMDEV="${MOUNTPATH##*/}"
CSOPTS=''
# process dm=
MOUNTPATH=$(echo "$*" | sed -e 's/.*dm=\([^,]*\)/\1/')
OPTS=$(echo "$*" | sed -e 's/\(.*\)dm=[^,]*\(.*\)/\1\2/g;s/\(.*\),/\1/')
# process ro
expr "$OPTS" : ro >/dev/null && CSOPTS='-r'
[ -b "${MOUNTPATH}" ] || die "Directory ${MOUNTPATH} is not a block device"
# TODO: handle mount options:
# encryption=cipher
# keybits=bits
# keyfd keyfile keyagent
# eject auto-eject on umount
/bin/cryptsetup luksOpen $CSOPTS "$MOUNTPATH" "$DMDEV" || die "cryptsetup failure"
/bin/mount -t auto /dev/mapper/$DMDEV $MOUNTPOINT -n -o $OPTS || {
/bin/cryptsetup remove "$DMDEV"
die "mount failure"
}
echo "/dev/mapper/$DMDEV $MOUNTPOINT dmcrypt $@,user=$DMCRYPT_USER 0 0" >>/etc/mtab
;;
/sbin/umount.dmcrypt)
UMOUNTPATH="$1"
grep " $UMOUNTPATH dmcrypt " /etc/mtab | {
read MOUNTPATH MOUNTPOINT dmcrypt OPTS z z
DMDEV="${MOUNTPATH##*/}"
umount -ni "$MOUNTPOINT"
/bin/cryptsetup luksClose "$DMDEV"
mv /etc/mtab /etc/mtab~
grep -v "^$MOUNTPATH $MOUNTPOINT dmcrypt " </etc/mtab~ >/etc/mtab
rm /etc/mtab~
}
;;
esac
mount.dmcrypt-luks Please note that I changed the Path of cryptsetup to where it resides in my Installation