Skip to content

Instantly share code, notes, and snippets.

@arpanpal010
Created July 29, 2014 05:50
Show Gist options
  • Save arpanpal010/ac9f610316d709da53aa to your computer and use it in GitHub Desktop.
Save arpanpal010/ac9f610316d709da53aa to your computer and use it in GitHub Desktop.
wrapper for cryptsetup with LUKS.
#!/bin/bash
#script wrapper to create/(u)mount/resize encrypted non-root filesystems using cryptsetup + LUKS
#does NOT unmount automatically on shutdown.
#Truecrypt is insecure.
#more info: https://wiki.archlinux.org/index.php/Dm-crypt
#TODO
#move functions to own module function
#improve cli
#added create
#added open/close
#added extend
#doesn't need root login to mount, although needs sudo
#does not preserve passwords
#only works with fstype ext2-3-4
#requires dd, sudo, cryptsetup, grep, head, (filemanager optional)
#filesystem type
fstype="ext4";
#opens file manager if set
FILE_MANAGER="pcmanfm";
#takes filepath and returns absolute filepath #$1=filename
function getabspath() {
echo `readlink -f "$1"`;
}
#get a mapper name from filename...e.g for container ~/priv.ate the mapper is priv #$1=filepath
function getmapper() {
fname=`basename "$1"`;
#echo $fname;
mapper=${fname%.*};
if [ "$mapper" == "" ]; then echo "Invalid Mapper. Exiting..."; exit;
else echo "$mapper";
fi;
}
#lists available loop devices
function listloop() {
losetup -a;
}
#list map devices in /dev/mapper
function listmap() {
ls /dev/mapper/;
}
#creating new containers - needs container path and size
function cryptcreate() {
#get abspath
filepath=`getabspath "$1"`;
#get mapper
mapper=`getmapper "$filepath"`;
#get bs and count
examt="$2";
#get block_size from size - use first one if erranously multiple
exunit="`echo "$2" | grep -io '[KMGT]\?' | head -n 1`";
#get count from size
excount="`echo "$2" | grep -o [0-9]*`";
if [ $excount -lt 0 ] || [ $excount -eq 0 ]; then echo "Cannot use size \"$2\""; exit; fi;
#validate given filepath
#file exists - prompt
if [ -f "$filepath" ] && [ -s "$filepath" ];
then
echo "Found file: $filepath";
#directory exists - reject
elif [ -d "$filepath" ];
then
echo "Cannot work with directory: $filepath";exit;
#file doesnt exist or zero size - try to create and fill
elif [ ! -e "$filepath" ] || [ ! -s "$filepath" ];
then
echo "Creating container at $filepath";
#try touch filepath exit if fails
touch "$filepath";
if [ $? -eq 1 ]; then echo "Failed to create \"$filepath\""; exit; fi;
#fill with random data from /dev/urandom
echo "Filling $filepath with random data. Blocksize=1${exunit^^}, Count=$excount..."
dd if=/dev/urandom of="$filepath" bs="1${exunit^^}" count="$excount";
echo "Done."
#everything else - exit
else
echo "Cannot find file: $filepath";exit;
fi;
#check if root, given only root can mount stuff
if (( $EUID != 0 )); then echo "Please provide sudo password for mount.";fi;
#get sudo password for mount
read -p "enter [sudo] password:" -s -r testpassword;
echo; #newline
#if not a LUKS container, exit..otherwise start setup LUKS
if [ `echo "$testpassword" | sudo -S cryptsetup isLuks "$filepath" && echo 1 || echo 0` == 1 ]
then
echo "Container is already setup LUKS Format. Try opening it...";
exit;
fi;
echo "Setting up LUKS container...";
#else mount container as loop device
echo "Mounting container as loop device..."
ld=`echo "$testpassword" | sudo -S losetup -f "$filepath" --show`;
echo "Loop device: $ld";
#create luks headers
echo "Creating LUKS header..."
#get sudo password for mount
read -p "enter [dm-crypt] password:" -s -r cryptpassword;
echo; #newline
#sudo has not timed out yet so no need for password #find alternative
echo -n "$cryptpassword" | sudo cryptsetup -v --cipher aes-xts-plain64 --key-size 512 --hash sha1 --iter-time 5000 --use-urandom --key-file - luksFormat "$ld";
#setting up filesystem
echo "Setting up filesystem..."
#get mapper and unlock
echo "Unlocking device \"$ld\" as \"$mapper\"";
sudo cryptsetup luksOpen "$ld" "$mapper";
#make filesystem with mkfs
echo -n "$testpassword" | sudo -S mkfs -t "$fstype" "/dev/mapper/$mapper";
#lock again
echo "Removing and locking map \"$mapper\"..."
echo -n $testpassword | sudo -S cryptsetup luksClose "$mapper";
#detach loop device before exit
echo "Detaching loop device $ld...";
echo -n "$testpassword" | sudo -S losetup -d $ld;
echo "Finished setting up LUKS in $filepath";
}
#open container - needs container path and mountpoint
function cryptopen() {
#show input
cfilepath=`getabspath "$1"`;
mfilepath=`getabspath "$2"`;
mapper=`getmapper "$cfilepath"`;
echo "Container: $cfilepath";
echo "Mountpoint: $mfilepath";
#if not root, given only root can mount stuff
if (( $EUID != 0 )); then echo "Please provide sudo password for mount.";fi;
#get sudo password for mount
read -p "enter [sudo] password:" -s -r testpassword;
echo; #newline
#mount container as loop device
echo "Mounting container as loop device..."
ld=`echo -n "$testpassword" | sudo -S losetup -f "$cfilepath" --show`;
if [ "$ld" == "" ]; then echo "Cannot loop container. Exiting";exit;
else
echo "Loop device: $ld";
fi;
#unlock loop device
echo "Unlocking container \"$ld\" as \"$mapper\"";
sudo cryptsetup luksOpen "$ld" "$mapper";
#mount map to filesystem - filepath=$2
echo "Mounting mapper in \"$mfilepath\"";
echo -n "$testpassword" | sudo -S mount "/dev/mapper/$mapper" "$mfilepath";
#try to open mountpoint in file manager
if [ "$FILE_MANAGER" != "" ]; then $FILE_MANAGER "$2";fi;
}
#close container - needs container path
function cryptclose() {
#get filepath
filepath=`getabspath "$1"`;
#get mapper from filename
mapper=`getmapper $filepath`;
#check if valid mapper
if [ "`listmap | grep -w "$mapper"`" != "" ];
then echo "Found mapper \"$mapper\".";
else echo "Mapper $mapper not found!"; exit;
fi;
#if not root, given only root can umount stuff
if (( $EUID != 0 )); then echo "Please provide sudo password for umount.";fi;
#get sudo password for mount
read -p "enter [sudo] password:" -s -r testpassword;
echo; #newline
#locate mapper in mtab
mt=`cat /etc/mtab | grep "/dev/mapper/$mapper"`;
#if mapper mounted
if [ "$mt" != "" ];
then #unmount mapper
echo "Unmounting: /dev/mapper/$mapper";
echo -n "$testpassword" | sudo -S umount "/dev/mapper/$mapper";
fi;
#lock container
echo "Removing and locking map \"$mapper\"..."
echo -n "$testpassword" | sudo -S cryptsetup luksClose "$mapper";
#find loop device and detach
ld=`echo "$testpassword" | sudo -S losetup -j $filepath | grep -o "/dev/loop[0-9]*"`;
echo "Detaching device $ld";
echo "$testpassword" | sudo -S losetup -d $ld;
echo "Done.";
}
#extend container - needs container path and size
function cryptextend() {
#get filepath
filepath=`getabspath $1`;
#get mapper from filename
mapper=`getmapper $filepath`;
#check if valid mapper, prompt unmount and exit if already mounted
if [ "`listmap | grep -w "$mapper"`" != "" ];
then echo "Before resize, please close Mapper \"$mapper\"."; exit;
fi;
#get bs and count
examt="$2";
#get block_size from size
exunit="`echo "$2" | grep -io '[KMGT]\?' | head -n 1`";
#get count from size
excount="`echo "$2" | grep -o [0-9]*`";
if [ $excount -lt 0 ] || [ $excount -eq 0 ]; then echo "Cannot use size \"$2\""; exit; fi;
#extend container size #>> do not overwrite
echo "Extending container with random data in $filepath with Block_size=1${exunit^^} and Count=$excount ";
dd if=/dev/urandom bs="1${exunit^^}" count="$excount" | cat - >> "$filepath";
echo "Done.";
#check if root, given only root can mount stuff
if (( $EUID != 0 )); then echo "Please provide sudo password for mount.";fi;
#get sudo password for mount
read -p "enter [sudo] password:" -s -r testpassword;
echo; #newline
#mount container as loop device
echo "Mounting container as loop device..."
ld=`echo "$testpassword" | sudo -S losetup -f "$filepath" --show`;
echo "Loop device: $ld";
#unlock loop device
mapper=`getmapper "$filepath"`;
echo "Unlocking container \"$ld\" as \"$mapper\"";
sudo cryptsetup luksOpen "$ld" "$mapper";
#resize mapper to maximum size available -> size of container
echo "$testpassword" | sudo -S cryptsetup resize "$mapper";
#check and resize filesystem
echo "$testpassword" | sudo -S e2fsck -f "/dev/mapper/$mapper" -y;
echo "$testpassword" | sudo -S resize2fs -p "/dev/mapper/$mapper";
#lock container
echo "Removing and locking map \"$mapper\"..."
echo -n "$testpassword" | sudo -S cryptsetup luksClose "$mapper";
#detach loop device before exit
echo "Detaching loop device $ld...";
echo -n "$testpassword" | sudo -S losetup -d "$ld";
echo "Finished resizing container $filepath";
}
#cli - sanitize arguments before forwarding
function cli() {
case "$1" in
"create") #create container
shift;
#if not enough arguments
if [ ! "$1" ] || [ ! "$2" ];
then
echo "Error: check arguments!";
echo "Usage: create /path/to/container size[KMGT]";
exit;
#elif invalid size
elif [ "`echo "$2" | grep -o [0-9]*`" == "" ] || [ "`echo "$2" | grep -io '[KMGT]'`" == "" ];
then
echo "Invalid size \"$2\"";
#else run function create
else cryptcreate "$1" "$2";
fi;
;;
"open") #open container
shift;
#if not enough arguments
if [ ! "$1" ] || [ ! "$2" ];
then
echo "Error: check arguments!";
echo "Usage: open /path/to/container /path/to/mountpoint";
#elif invalid or size-zero container filepath
elif [ ! -f "$1" ] || [ ! -s "$1" ]; then echo "Container not found at \"$1\"";
#elif invalid mountpoint dir
elif [ ! -d "$2" ]; then echo "Mountpoint not found at \"$2\"";
#else run function open
else cryptopen "$1" "$2";
fi;
;;
"close") #close container
shift;
#if not enough arguments or size-zero container filepath
if [ ! -f "$1" ] || [ ! -s "$1" ];
then
echo "Error: check arguments!";
echo "Usage: close /path/to/container";
exit;
#else run function close
else cryptclose "$1";
fi;
;;
"extend") #extend container
shift;
#if not enough arguments
if [ ! "$1" ] || [ ! "$2" ];
then
echo "Error: check arguments!";
echo "Usage: extend /path/to/container size[KMGT]";
#elif invalid container path
elif [ ! -f "$1" ] || [ ! -s "$1" ]; then echo "Container not found at \"$1\"";
#elif invalid size
elif [ "`echo "$2" | grep -o [0-9]*`" == "" ] || [ "`echo "$2" | grep -io '[KMGT]'`" == "" ];
then
echo "Invalid size \"$2\"";
echo "Usage: extend /path/to/container size[KMGT]";
#else run function extend
else cryptextend "$1" "$2";
fi;
;;
#extra functions (not to be used without knowing what they do, or don't do)
"unmount") #unmounts device if mounted
cryptumount "$1";
;;
"listmap") #lists mapped devices
listmap;
;;
"listloop") #lists used loop devices
listloop;
;;
*) #echo usage
echo "Error: check arguments!";
echo "Usage:";
echo "sh ./$0 create /path/to/container size[KMGT]";
echo "sh ./$0 open /path/to/container /path/to/mountpoint";
echo "sh ./$0 close /path/to/container";
echo "sh ./$0 extend /path/to/container size[KMGT]";
;;
esac
}
#run cli
cli "$@";
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment