#!/bin/bash

# UsbCryptFormat
# Version: 10.02.05
# by Markus Mandalka - http://mandalka.name


# print error message and abbort installing
error()
{
  echo "$@"
  $DIALOG --title "Error" --msgbox "$@" 0 0;
  exit 1;
}


unmount_device()
{
  # unmount device
  umount $@ >/dev/null 2>/dev/null

  # unmount all partitions on the device
  dev_part=${@/\/dev\/}
  for partition in $(udevadm info --export-db| egrep -o "/block/${dev_part}/.*");
  do
    devicepartition="/dev/$(udevadm info --query=name -p ${partition})"
    umount $devicepartition >/dev/null 2>/dev/null
  done
}




# Language and messages

title_select="UsbCryptFormat";
msg_select="\nChoose an usb-device (usb-key or external harddisk)
to be formated with an encrypted filesystem:"

menuitem_none="None"
menuitem_none_description="No device"

title_done="Encryption done"
msg_done="Encryption done.

Next time you insert this media, you will be asked for the password."

msg_error_password="Error: The passwords did not match!"
title_password="Password"
msg_password_1="Password"
msg_password_2="Checking password"


msg_overwrite_ask_title="Overwrite old data?";

msg_overwrite_ask="
Overwrite old data on the device with random data?

This may take long time.

But if you don't do it:
- parts of the data, that were on the device before
the encryption could be restored by others very easy.
- others can find out, how much data is saved 
inside the encrypted partition.

If it is not only a test, choose [yes] here !

Overwrite old data?";
title_overwrite="Deleting old data";
msg_overwrite="\nOverwriting device with random data ...";

title_are_you_sure="Danger: Data on this device will be deleted!!!";
msg_are_you_sure1="Are you absoluteley sure, that data on this device
should be overwritten?

"
msg_are_you_sure2="

If you selected the wrong device you will loose all data
on the usb-key or on the external harddisk!

If you choose < Yes >, there will be no return!

Realy continue and overwrite the selected device?";

msg_error_mounted="The selected device is mounted!

Please unmount it and start again!";


# Messages not used by the gui
# You don't have to translate them to support another language

msg_error_luksformat="Error while luksformat!";
msg_error_luksopen="Error while luksopen!";
msg_overwrite_done="Overwrite done.";
msg_luksformat="Encrypting device ...";
msg_luksopen="Opening encrypted device ...";
msg_error_mkfs="Error while making filesystem! Abort.";
msg_error_mount="Error while mounting ! Abort.";
msg_error_umount="Error while umount ! Abort.";
msg_error_luksclose="Error while closing devicemaper with luksClose! Abort.";
msg_mkfs="

Formating root-filesystem:

";
msg_sfdisk="Writing partitiontable ...";
msg_mount="
Mount partition ...";

msg_umount="Umount filesystem ...";

msg_error_sfdisk="Error while writing partition table with sfdisk !";

msg_error_mkdir_mount_target="Error while making temp-directory!";
msg_choice="Choice: ";
msg_overwrite_part="Deleting old partition infos ...";



case "$LANG" in
de*|at*|ch*)

title_select="UsbCryptFormat";
msg_select="Wählen Sie das zu verschlüsselnde Gerät
(Speicherkarte, USB-Stick oder externe Festplatte):"

menuitem_none="None"
menuitem_none_description="Kein Gerät"

title_done="Verschlüsselung abgeschlossen"
msg_done="Das Formatieren wurde erfolgreich abgeschlossen.

Sie werden beim erneuten Einstecken des Datenträgers
nach dessen Passwort gefragt."

msg_error_password="Fehler: Das Passwort stimmt nicht überein!"
title_password="Passwort";
msg_password_1="Verschlüsselungspasswort eingeben:"
msg_password_2="Bitte das Verschlüsselungspasswort wiederholen:"

msg_overwrite_ask_title="Alte Daten überschreiben?"
msg_overwrite_ask="
Soll der Datenträger mit Zufallsdaten überschrieben werden?

Dieser Schritt dauert bei grossen Festplatten sehr lange.

Wird das Überschreiben jedoch nicht durchgeführt,
- können Teile der Daten, die sich vor dem Verschlüsseln auf diesem
Datenträger befunden haben, mit einfachsten Mitteln wieder her gestellt werden
- kann herausgefunden werden, wie viel Speicherplatz
im verschlüsselten Bereich tatsächlich belegt ist.

Falls es sich nicht um eine reine Testformatierung handelt,
sollten Sie [Ja] wählen!

Sollen vor dem Formatieren alte Daten überschrieben werden?";
title_overwrite="Lösche alte Daten";
msg_overwrite="\nDer Datenträger wird mit Zufallsdaten überschrieben ...";
title_are_you_sure="Achtung: Daten auf diesem Datenträger werden gelöscht!!!";
msg_are_you_sure1="Sind Sie sich absolut sicher, dass der nachfolgende Datenträger
verwendet werden soll?

";
msg_are_you_sure2="

Falls Sie das falsche Gerät gewählt haben,
werden Daten auf einem anderen USB-Speicher
oder einer externen Festplatte überschrieben!

Wenn Sie mit < Ja > bestätigen, gibt es kein Zurück mehr
und auf dem gewählten Datenträger vorhandenen Daten sind verloren!

Wirklich fortfahren und den Datenträger formatieren?";

msg_error_mounted="Der zu verschlüsselnde Datenträger ist noch eingehängt
und wird offenbar noch genutzt!

Bitte schliessen Sie alle Programme, die auf Dateien des Datenträgers zugreifen,
hängen Sie den Datenträger aus und führen Sie dann dieses Programm erneut aus!";

# Messages not used by the gui
# You don't have to translate them to support another language

msg_overwrite_done="Das Überschreiben ist abgeschlossen.";
msg_umount="Hänge das Filesystem wieder aus ...";
msg_error_luksformat="Fehler beim Aufruf von luksformat!";
msg_error_luksopen="Fehler beim Aufruf von luksopen!";
msg_error_mount="Fehler beim Mounten der Partition ! Abbruch.";
msg_error_umount="Fehler beim Aushängen (umount) ! Abbruch.";
msg_error_mkfs="Fehler beim Anlegen des Dateisystems ! Abbruch.";
msg_error_luksclose="Fehler beim Schliessen des Devicemappers mit luksClose! Abbruch.";
msg_luksformat="Verschlüssele das Gerät ...";
msg_luksopen="Öffne verschlüsseltes Gerät ...";

msg_mkfs="

Formatiere das Dateisystem:

";
msg_sfdisk="Schreibe Partitionstabelle ...";

msg_mount="
Mounte die Partition ...";
msg_umount="Hänge das Filesystem wieder aus ...";

msg_error_sfdisk="Fehler beim Schreiben der Partitionstabelle mit sfdisk !";

msg_error_mkdir_mount_target="Fehler beim Erstellen des Temporär-Verzeichnisses !";
msg_choice="Gewählter Datenträger: ";
msg_overwrite_part="Lösche alte Partitions-Informationen ...";

;;
esac


# Get root
[ "`id -u`" != "0" ] && exec sudo "$0" "$@"

mount_target="/tmp/usbcryptformat-$$";

if [ -e /usr/bin/Xdialog ]
then
  DIALOG="Xdialog"
else
  DIALOG="dialog"
fi

echo -en "\033]2;UsbCryptFormat\007"
echo "UsbCryptFormat 10.02.05"
echo "Copyleft by Markus Mandalka - http://mandalka.name"
echo
echo "Powered by cryptsetup, dm-crypt/luks, xdialog, bash, gnu/linux ..."
echo

# Select USB-Device
TEMPFILE=/tmp/selection.$$

if ! partsel --exclude-crypttab -d $DIALOG -f usb-devices -o $TEMPFILE -t "$title_select" -m "$msg_select" -nt "$menuitem_none" -nd "$menuitem_none_description"
then
  exit
fi

choice=`cat $TEMPFILE`
rm $TEMPFILE

if [ "$choice" == "$menuitem_none" ];
then
   exit
fi

device=$choice;

echo "${msg_choice}$device"
echo


# Get infos about the device to ask, if it is the right one
model=$(udevadm info --query=env -p `udevadm info -q path -n $device` 2>/dev/null | grep "ID_MODEL=" | cut -f 2 -d "=" | sed s/_/\ /g| tr -d [:punct:])
bus=$(udeadm vinfo --query=env -p `udevadm info -q path -n $device` 2>/dev/null | grep "ID_BUS=" | cut -f 2 -d "=" | sed s/_/\ /g)
size=$(LC_ALL=C fdisk -l $device 2>/dev/null | grep Disk | grep -i bytes | cut -f 1 -d "," | cut -f 3,4 -d " ");
vendor=$(udevadm info --query=env -p ${partition} 2>/dev/null | grep "ID_VENDOR=" | cut -f2 -d'='|sed s/_/\ /g| tr -d [:punct:])

modelandvendor="$model";
[ -n "$vendor" ] && modelandvendor="$modelandvendor ($vendor)";
msg_are_you_sure="$msg_are_you_sure1$device: $modelandvendor - $size$msg_are_you_sure2"

if ! $DIALOG --title "$title_are_you_sure" --yesno "$msg_are_you_sure" 0 0;
  then
    exit
fi;

unmount_device $device;

# check if the device or a parition on the device is mounted
if cat /etc/mtab | grep $device && echo $?
  then
    error "$msg_error_mounted";
fi

# Ask password
PASSWORD1=$($DIALOG --stdout --title $title_password --passwordbox "$msg_password_1" 0 0) || exit
PASSWORD2=$($DIALOG --stdout --title $title_password --passwordbox "$msg_password_2" 0 0) || exit

if [ "$PASSWORD1" != "$PASSWORD2" ]
then
  error "$msg_error_password";
  exit 1;
fi
PASSWORD2="";



# ask if overwrite old data
if $DIALOG --title "$msg_overwrite_ask_title" --yesno "$msg_overwrite_ask" 0 0;
then

  echo "$title_overwrite"

  # Overwrite old data on whole device
  dd bs=2M if=/dev/urandom | pv -n --size=$(fdisk -s $device)k 2>&1 >$device | $DIALOG --title "$title_overwrite" --gauge "$msg_overwrite" 0 0;
  clear;
  echo "$msg_overwrite_done";

else
  # Overwrite begin of the old partition,
  # so that the system won't try to mount it
  # after following initialize of the new partition table
  echo "$msg_overwrite_part";
  dd bs=2M count=1 if=/dev/zero of=$device
  clear;
fi;


# Create partitions
echo "$msg_sfdisk";
if ! sfdisk $device -L<<EOF
,,L
EOF
then
 error "$msg_error_sfdisk";
fi

# Read new partition table
partprobe $device

clear;

# Set device to first partition
device=${device}1

# Yet existing (if not overwritten) filesystems could be mounted again after rereading new partition table, so we unmount it again
umount $device >/dev/null 2>/dev/null

modprobe dm-crypt

# crypt device
echo "$msg_luksformat";
if ! echo -n "$PASSWORD1" | cryptsetup --batch-mode luksFormat $device
then
 error "$msg_error_luksformat";
fi;


# open crypted device
echo "$msg_luksopen";
if ! echo -n "$PASSWORD1" | cryptsetup luksOpen $device usbcryptformat$$
then
 error "$msg_error_luksopen";
fi;

PASSWORD1="";

# create filesystem
echo "$msg_mkfs_root"
if ! mkfs.ext3 /dev/mapper/usbcryptformat$$
then
 error "$msg_error_mkfs";
fi;

if ! mkdir $mount_target
then
  error "msg_error_mkdir_mount_target";
fi

if ! mount /dev/mapper/usbcryptformat$$ $mount_target
then
  error "$msg_error_mount";
fi

chown 1000:1000 $mount_target

echo "$msg_umount";
if ! umount $mount_target
then
  error "$msg_error_umount";
fi


if ! cryptsetup luksClose usbcryptformat$$
then
  error "$msg_error_luksclose";
fi

rmdir $mount_target
echo
echo "$title_done"
$DIALOG --title "$title_done" --msgbox "$msg_done" 0 0
