#!/bin/sh

#
# This script opens and closes LUKS encrypted key store.
#

# Copyright (C) 2020 Canonical
#
# Authors:
# Jean-Baptiste Lallement <jean-baptiste@ubuntu.com>
# Didier Roche <didrocks@ubuntu.com>
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation; version 3.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA

set -eu

KEYSTORE=/run/kstore

usage() {
    # Display script usage
    cat<<EOF
Usage: $(basename "$0") [COMMAND] [OPTIONS...]
    Open and close the keystore.

Commands:
    unlock  Open the keystore, need passphrase on stdin.
    lock    Close the keystore
Options:
    -h, --help      This help
    -d, --debug     Enable debug mode
EOF
    exit
}

SHORTOPTS="hd"
LONGOPTS="help,debug"

TEMP=$(getopt -o $SHORTOPTS --long $LONGOPTS -- "$@")
eval set -- "$TEMP"

while true ; do
    case "$1" in
        -h|--help)
            usage;;
        -d|--debug)
            set -x
            shift;;
        --)
            shift;
            break;;
        *)
            usage;;
    esac
done

COMMAND=$( echo $1 | tr '[:upper:]' '[:lower:]' )


if [ "${COMMAND}" = "lock" ]; then
	pool="$2"
	user="$3"
	if [ -n "$(ls -A ${KEYSTORE}/${pool}/${user})" ]; then
		umount ${KEYSTORE}/${pool}/${user}
	fi
	devmapper="/dev/mapper/kstore-${pool}-${user}"
	if [ -e "${devmapper}" ]; then
		cryptsetup luksClose "${devmapper}"
	fi
	for loopdev in $(losetup -O NAME -n -j "${KEYSTORE}/${pool}/${user}.enc"); do
		losetup -d "${loopdev}"
	done

elif [ "${COMMAND}" = "unlock" ]; then
	user=${PAM_USER:-$2}
	home=$(getent passwd "${user}" | cut -d: -f6 | cut -c2-)
	homeunit="/run/systemd/generator/$(systemd-escape "${home}").mount"

	if [ ! -f "${homeunit}" ]; then
		echo "Didn’t find any generated mount units for user. Skipping"
		exit 0
	fi

	devpath="$(grep What ${homeunit} | cut -d= -f2-)"

	dev=""
	if echo "${devpath}" | grep -q "^/dev/"; then
		dev="${devpath##*/}"
	else
		dev="${devpath%%/*}"
	fi

	mapper="kstore-${dev}-${user}"
	if [ -e "/dev/mapper/${mapper}" ]; then
		exit 0
	fi

	keypath="$(readlink -f ${KEYSTORE}/${dev}/${user}.enc)"
	if [ ! -e "$keypath" ]; then
		exit 0
	fi

	loopdevice=$(losetup --show -f "$keypath")
	if [ ! -e "$loopdevice" ]; then
		echo "E: Couldn't allocate loop device for user $user and key $keypath"
		exit 1
	fi

	tr '\0' '\n' | /sbin/cryptsetup luksOpen ${loopdevice} "${mapper}"

	mount /dev/mapper/${mapper} ${KEYSTORE}/${dev}/${user}

else
	echo "E: Unknown command: ${COMMAND}"
	usage
fi
