#!/bin/bash

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


# print error message and abbort installing
error()
{
  echo "$@"
  zenity --error --title "Error" --text "$@";
  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:"

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):"

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-$$";

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

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

if ! partsel --exclude-crypttab -f usb-devices -o $TEMPFILE -t "$title_select" -m "$msg_select"
then
  exit
fi

choice=`cat $TEMPFILE`
rm $TEMPFILE

if [ -z ${choice} ]
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 ! zenity --question --title "$title_are_you_sure" --text "$msg_are_you_sure";
  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=$(zenity --entry --hide-text --title $title_password --text "$msg_password_1") || exit
PASSWORD2=$(zenity --entry --hide-text --title $title_password --text "$msg_password_2") || exit

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



# ask if overwrite old data
if zenity --question --title "$msg_overwrite_ask_title" --text "$msg_overwrite_ask";
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 | zenity --auto-close --title "$title_overwrite" --progress --text "$msg_overwrite";
  dd bs=2M if=/dev/urandom | pv --size=$(fdisk -s $device)k 2>&1 >$device
  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;

sync

# 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

sync

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


# open crypted device
echo "$msg_luksopen";
if ! echo -n "$PASSWORD1" | cryptsetup luksOpen $device usbcryptformat$$
then
    if ! echo -n "$PASSWORD1" | cryptsetup luksOpen $device usbcryptformat$$
    then
     error "$msg_error_luksopen";
    fi;
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"
zenity --info --title "$title_done" --text "$msg_done"
