1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
|
#!/bin/bash
#
# /etc/hotplug.d/block/cryptostick.hotplug
#
# description:
# skript checks for certain USB-sticks plugged in, loads and reconstructs
# AES256 keys by xor and runs cryptsetup to setup a dm-crypt device to decrypt
# an encrypted raw partition. it automatically mounts the dm-crypt device.
#
# depends on: cryptsetup, procmail (lockfile), e2fsprogs
#
# Author: Volker Sauer <vsauer@dvs1.informatik.tu-darmstadt.de>
# Version: 1.0
# License: GPL
#
# Only use USB stick partition with the following ext2/3 UUID (leave empty to disable check):
FS_UUID="c3d9cb8e-1cb5-485c-9369-6404ec57b2c0"
#
CRYPTRAWVOL=/dev/loop0 # RAW volume to be decrypted
CRYPTVOLNAME=stuff # name of decrypted volume (in /dev/mapper)
CRYPTVOLMNT=/export/stuff # mountpoint the decrypted volume
STICKKEYDIR=/keys # directory with the keys on the USB stick
HOSTKEYDIR=/etc/keys # directory with host keys of this computer
CRYPTSETUP=/sbin/cryptsetup # needed to setup dm-crypt (package cryptsetup)
MOUNT=/bin/mount # just in case you have your own mount program...
RUN_EXPORTFS=no # run "exportfs -r" after successfull mount?
TUNE2FS=/sbin/tune2fs # tune2fs needed to check for ext2/3 fs UUID (e2fsprogs)
LOCKFILE=/var/lock/cryptostick.hotplug # lockfile for this script
LOCK_CMD=/usr/bin/lockfile # lock programm from procmail (package procmail)
export DEBUG=yes
source /etc/hotplug/hotplug.functions
# devices need a little time to appear in /sys:
sleep 1
# Serialize script execution
$LOCK_CMD -sleeptime 2 -r 1 -locktimeout 5 $LOCKFILE
DEVICE=$(echo "${DEVPATH}" | awk -F\/ '{ print $3 }')
PARTITION=$(echo "${DEVPATH}" | awk -F\/ '{ print $4 }')
BUS=`ls -l /sys/block/$DEVICE/device|awk -F/ '{print $10}'`
myexit(){
rm -f $LOCKFILE
exit $1
}
# I only handle block device messages
if [ "$1" != "block" ]; then
debug_mesg "I only handle block device messages. Exiting"
myexit 0
fi
# I'm only interested in "add" events
if [ "$ACTION" != "add" ]; then
debug_mesg "Got action $ACTION. Not interested in that. Exiting"
myexit 0
fi
# I'm only interested in USB devices
if [ "$(echo $BUS|cut -b 1-3)" != "usb" ]; then
debug_mesg "I only care about USB devices but not $DEVICE. Exititing"
myexit 0
fi
# Check if RAW-Volume exists
if [ ! -b $CRYPTRAWVOL ]; then
mesg "(RAW) Volume $CRYPTRAWVOL does not exist or is not a block device"
myexit 1
fi
# Check if volume is already mounted
while read dev mntpath rest; do
if [ "$mntpath" = "$CRYPTVOLMNT" ]; then
debug_mesg "Volume $CRYPTVOLMNT is already mounted, exiting."
myexit 0
fi
done < /proc/self/mounts
# Check if dm-crypt is already setup
if [ -b /dev/mapper/$CRYPTVOLNAME ]; then
mesg "/dev/mapper/$CRYPTVOLNAME already exists. Trying to mount...."
$MOUNT /dev/mapper/$CRYPTVOLNAME $CRYPTVOLMNT
if [ "$?" == "0" ]; then
mesg "/dev/mapper/$CRYPTVOLNAME successfully mounted in $CRYPTVOLMNT"
myexit 0
else
mesg "($?) could not mount /dev/mapper/$CRYPTVOLNAME. Exiting"
myexit 0
fi
fi
# Fetches the key from the partition/device and runs crypsetup
get_key_from_device(){
# Check if fs uuid is wanted and correct
if [ ! -z $FS_UUID ]; then
debug_mesg "Checking UUID of /dev/$1"
uid=`$TUNE2FS -l /dev/$1 2>/dev/null |grep "Filesystem UUID:"` || exit 1;
uid=`echo $uid|awk '{print $3}'`
debug_mesg "Found UUID: $uid on /dev/$1"
if [ "$uid" != "$FS_UUID" ]; then
mesg "Wrong filesystem UUID $uid found on /dev/$1. Exititing"
myexit 1
fi
fi
STICKMNT=`mktemp -d`|| exit 1 # where to (temporarily) mount usb stick
debug_mesg "Trying to get key from /dev/$1. Mounting at $STICKMNT"
$MOUNT -o ro /dev/$1 $STICKMNT
if [ "$?" != "0" ]; then
debug_mesg "Unable to mount /dev/$1. Exiting"
rmdir $STICKMNT || mesg "Unable to remove temporary mountpoint $STICKMNT"
myexit 1
fi
if [ ! -d $STICKMNT/$STICKKEYDIR ]; then
debug_mesg "Directory $STICKMNT/$STICKKEYDIR does not exist. Unmounting /dev/$1"
umount $STICKMNT
rmdir $STICKMNT || mesg "Unable to remove temporary mountpoint $STICKMNT"
myexit 1
fi
HOSTNAME=`hostname`
if [ ! -e $STICKMNT/$STICKKEYDIR/$HOSTNAME*.key ]; then
debug_mesg "There is no key for $HOSTNAME in $STICKMNT/$STICKKEYDIR/. Unmounting $1"
umount $STICKMNT
rmdir $STICKMNT || mesg "Unable to remove temporary mountpoint $STICKMNT"
myexit 1
else
COUNT=`ls $STICKMNT/$STICKKEYDIR/$HOSTNAME*.key|wc -w`
if [ $COUNT -gt 1 ]; then
mesg "I found $COUNT keys for $HOSTNAME on /dev/$1. Please provide only one key per host. Exiting"
umount $STICKMNT
rmdir $STICKMNT || mesg "Unable to remove temporary mountpoint $STICKMNT"
myexit 1
else
KEYNAME=`ls $STICKMNT/$STICKKEYDIR/$HOSTNAME*.key`
KEYNAME=`basename $KEYNAME`
mesg "Using /dev/$1/keys/$KEYNAME as userkey"
HOSTKEY=`echo $KEYNAME|cut -d. -f1`.host
if [ ! -e $HOSTKEYDIR/$HOSTKEY ]; then
mesg "Machtching hostkey $HOSTKEYDIR/$HOSTKEY. Exiting"
rmdir $STICKMNT || mesg "Unable to remove temporary mountpoint $STICKMNT"
myexit 1
else
mesg "Using $HOSTKEYDIR/$HOSTKEY as hostkey"
fi
perl -e 'open(F2,@ARGV[0]) && open(F1,@ARGV[1]) or die "Usage: $0 <file1> <file2>\n"; print $buf1 ^ $buf2 while (read (F1,$buf1,65536) && read (F2,$buf2,65536));' -- $STICKMNT/$STICKKEYDIR/$KEYNAME $HOSTKEYDIR/$HOSTKEY | $CRYPTSETUP create $CRYPTVOLNAME $CRYPTRAWVOL
if [ "$?" != "0" ]; then
mesg "($?) cryptsetup failed. This should not happen"
rmdir $STICKMNT || mesg "Unable to remove temporary mountpoint $STICKMNT"
myexit 1
fi
debug_mesg "mount /dev/mapper/$CRYPTVOLNAME $CRYPTVOLMNT"
$MOUNT /dev/mapper/$CRYPTVOLNAME $CRYPTVOLMNT
if [ "$?" = "0" ]; then
mesg "/dev/mapper/$CRYPTVOLNAME successfully mounted at $CRYPTVOLMNT"
if [ "$RUN_EXPORTFS" == "yes" ]; then
if [ -x /usr/sbin/exportfs ]; then
debug_mesg "Running exportfs -r"
/usr/sbin/exportfs -r
if [ "$?" != "0" ]; then
mesg "Could not run exportfs -r"
fi
else
mesg "/usr/sbin/exportfs does not exist on this computer. Maybe it isn't an NFS-Server?"
fi
fi
else
mesg "($?) could not mount /dev/mapper/$CRYPTVOLNAME. Exiting"
umount $STICKMNT
rmdir $STICKMNT || mesg "Unable to remove temporary mountpoint $STICKMNT"
mesg "Removing cryptsetup for $CRYPTVOLNAME"
$CRYPTSETUP remove $CRYPTVOLNAME || mesg "done"
myexit 1
fi
umount $STICKMNT
rmdir $STICKMNT || mesg "Unable to remove temporary mountpoint $STICKMNT"
fi
fi
}
debug_mesg "Action: $ACTION of $DEVICE, partition: $PARTITION on bus $BUS"
if [ -z $PARTITION ]; then
# debug_mesg "Trying block device $DEVICE *without* partition."
get_key_from_device $DEVICE
else
get_key_from_device $PARTITION
fi
rm -f $LOCKFILE
|