#!/bin/sh

#   FILE: mkehd -- Create an encrypted home directory disk image.
# AUTHOR: W. Michael Petullo <mike@flyn.org>
#   DATE: 06 October 2002
# 
# Copyright (C) 2002 W. Michael Petullo <mike@flyn.org>
# All rights reserved.
# 
# 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; either version 2 of the License, or
# (at your option) any later version.
# 
# 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

CONF=/etc/security/pam_mount.conf
CIPHER=aes
KEYBITS=256
SIZE=20
FSTYPE=ext2
_USER=$USER

USAGE="[OPTION]...

  -h, -?      print this message
  -c cipher   set the cipher used in the filesystem [ $CIPHER ]
  -i cipher   set the fsk cipher                    [ from pam_mount.conf ]
  -f filename name of the disk image to generate    [ from pam_mount.conf ]
  -k keybits  set the number of bits in cipher key  [ $KEYBITS ]
  -p path     set the path to the efsk              [ from pam_mount.conf ]
  -s size     size in MB of generated filesystem    [ $SIZE ]
  -t fs type  type of filesystem to create          [ $FSTYPE ]
  -u user     name of user to create ehd for        [ $_USER ]"

while :;
	do case "$1" in
		-h | "-?" )	
			echo -e usage: ${0##*/} "$USAGE" >&2
			exit 1 ;;
		-c )
			CIPHER=$2
			shift ;;
		-f )
			FILENAME[0]=$2
			shift ;;
		-i )
			FSK_CIPHER=$2
			shift ;;
		-p )
			KEYPATH=$2
			shift ;;
		-s )
			SIZE=$2
			shift ;;
		-u )
			_USER=$2
			shift ;;
		-?* )
			echo "${0##*/}: unrecognised option: $1" >&2
			exit 1 ;;
		* )
			break ;;
	esac
	shift
done

if [ ! -f $CONF ]; then
	echo "${0##*/}: $CONF is missing"
	exit 1
fi

volcount=0
# if no image filename is specified then we grab all out of pam_mount.conf
if [ -z ${FILENAME[0]} ]; then 
	while read LINE; do
		if echo $LINE | grep "^volume ${_USER}" > /dev/null; then
			FILENAME[$volcount]=`echo $LINE | awk '{ print $5 }'`
			FSK_CIPHER[$volcount]=`echo $LINE | awk '{ print $8 }'`
			KEYPATH[$volcount]=`echo $LINE | awk '{ print $9 }'`
			volcount=$(($volcount + 1))
		fi
	done < $CONF
	volcount=$(($volcount - 1))
fi

if [ -z $PASSWORD ]; then
	echo -n "(current) UNIX password: "
	stty -echo > /dev/tty
	read PASSWORD < /dev/tty; echo
	echo -n "Retype UNIX password: "
	read VERIFY < /dev/tty; echo
	if [ ${PASSWORD} != ${VERIFY} ]; then
		echo "Sorry, passwords do not match"
		stty echo > /dev/tty
		exit 1
	fi
	stty echo > /dev/tty
fi

for (( ; $volcount >= 0; volcount=$(($volcount - 1)) )); do
	if [ x${FSK_CIPHER[$volcount]} != x- ]; then
		echo Using encrypted filesystem key...
		if [ x"${KEYPATH[$volcount]}" = x- ]; then
			echo "${0##*/}: \"fs key path\" not defined in "
			echo "$CONF for user $_USER"
			echo
			echo "You need to edit $CONF correctly for efsk method."
			exit 1
		fi
		if [ -f ${KEYPATH[$volcount]} ]; then
			echo "${0##*/}: ${KEYPATH[$volcount]} already exists: don't want to risk losing it"
			exit 1
		fi
		if [ -f ${FILENAME[$volcount]} ]; then
			echo "${0##*/}: ${FILENAME[$volcount]} already exists: don't want to risk losing it"
			exit 1
		fi
		echo "Creating filesystem image using /dev/urandom (may take a LONG time)..."
		dd if=/dev/urandom of=${FILENAME[$volcount]} bs=1M count=$SIZE > /dev/null
		# Use a named pipe because env. vars. are viewable by all 
		# and random string is already being piped into openssl's 
		# stdin
		SYS_PASS_PIPE=`mktemp -u /tmp/mkehd.XXXXXX`
		mkfifo -m 0600 $SYS_PASS_PIPE
		echo $PASSWORD > $SYS_PASS_PIPE &
		dd if=/dev/urandom bs=1c count=$(($KEYBITS / 8)) | openssl enc -${FSK_CIPHER[$volcount]} -pass file:$SYS_PASS_PIPE > ${KEYPATH[$volcount]}
		echo $PASSWORD > $SYS_PASS_PIPE &
		openssl enc -d -${FSK_CIPHER[$volcount]} -in ${KEYPATH[$volcount]} -pass file:$SYS_PASS_PIPE | losetup -e $CIPHER -k $KEYBITS -p0 /dev/loop1 ${FILENAME[$volcount]}
		mkfs -t $FSTYPE /dev/loop1 > /dev/null
		losetup -d /dev/loop1
		rm $SYS_PASS_PIPE
	else
		echo NOT using encrypted filesystem key...
		echo "Creating filesystem image using /dev/urandom (may take a LONG time)..."
		dd if=/dev/urandom of=${FILENAME[$volcount]} bs=1M count=$SIZE
		echo $PASSWORD | losetup -e $CIPHER -k $KEYBITS -p0 /dev/loop1 ${FILENAME[$volcount]}
		mkfs -t $FSTYPE /dev/loop1 > /dev/null
		losetup -d /dev/loop1
	fi
done
