#!/bin/sh
#
# This file, originally written by Garrett A. Wollman, is in the public
# domain.
#
# $FreeBSD: src/etc/rc.d/gbde,v 1.12.2.1 2005/08/16 08:39:36 pjd Exp $
#
# Hacked by Andrew Donofrio [AD] to support random keying
# of GBDE disk encryption for the device mounted as /tmp. Some script
# code copied from $FreeBSD: src/etc/rc.d/encswap in the process. Use
# this script at your own risk. This is unsupported, and all code by
# AD in here is released in the public domain.
#
# AD 28-12-2005 v0.0.0.0.1
#

# PROVIDE: disks
# REQUIRE: initrandom
# KEYWORD: nojail

. /etc/rc.subr

name="gbde"
start_precmd="find_gbde_devices start"
stop_precmd="find_gbde_devices stop"
start_cmd="gbde_start"
stop_cmd="gbde_stop"

find_gbde_devices()
{
        case "${gbde_devices-auto}" in
        [Aa][Uu][Tt][Oo])
                gbde_devices=""
                ;;
        *)
                return 0
                ;;
        esac

        case "$1" in
        start)
                fstab="/etc/fstab"
                ;;
        stop)
                fstab=$(mktemp /tmp/mtab.XXXXXX)
                mount -p >${fstab}
                ;;
        esac

        #
        # We can't use "mount -p | while ..." because when a shell loop
        # is the target of a pipe it executes in a subshell, and so can't
        # modify variables in the script.
        #
        while read device mountpt type options dump pass; do
                case "$device" in
                *.bde)
                        # Ignore swap devices
                        case "$type" in
                        swap)
                                continue
                                ;;
                        esac

                        case "$mountpt" in
                        /tmp)
                                gbde_devices="${gbde_devices} ${device}.tmp"

                                continue
                                ;;
                        esac

                        case "$options" in
                        *noauto*)
                                if checkyesno gbde_autoattach_all; then
                                        gbde_devices="${gbde_devices} ${device}"
                                fi
                                ;;
                        *)
                                gbde_devices="${gbde_devices} ${device}"
                                ;;
                        esac
                        ;;
                esac
        done <${fstab}

        case "$1" in
        stop)
                rm -f ${fstab}
                ;;
        esac

        return 0
}

gbde_start()
{
        for device in $gbde_devices; do
                passphrase="empty"
                case "$device" in
                *.bde.tmp)
                        parent=${device%.tmp}
                        passphrase=`dd if=/dev/random count=1 2>/dev/null | sha256 -q`
                        ;;
                esac
                parent=${parent%.bde}
                parent=${parent#/dev/}
                if [ -e "/dev/${parent}" -a ! -e "/dev/${parent}.bde" ]; then
                        echo "Configuring Disk Encryption for ${parent}."

                        count=1
                        while [ ${count} -le ${gbde_attach_attempts} ]; do
                                if [ "empty" != "${passphrase}" ]; then
                                        gbde init "/dev/${parent}" -P "${passphrase}"
                                        gbde attach "${parent}" -p "${passphrase}"
                                        newfs "/dev/${parent}.bde"
                                        mount /tmp
                                        chmod 1777 /tmp
                                        umount /tmp
                                else
                                        parent_=`ltr ${parent} '/' '_'`
                                        eval "lock=\${gbde_lock_${parent_}-\"${gbde_lockdir}/${parent_}.lock\"}"
                                        if [ -e "${lock}" ]; then
                                                gbde attach "${parent}" -l "${lock}"
                                        else
                                                gbde attach "${parent}"
                                        fi
                                fi
                                if [ -e "/dev/${parent}.bde" ]; then
                                        break
                                fi
                                echo "Attach failed; attempt ${count} of ${gbde_attach_attempts}."
                                count=$((${count} + 1))
                        done
                fi
        done
}

gbde_stop()
{
        for device in $gbde_devices; do
                parent=${device%.tmp}
                parent=${parent%.bde}
                parent=${parent#/dev/}
                if [ -e "/dev/${parent}.bde" ]; then
                        umount "/dev/${parent}.bde" 2>/dev/null
                        gbde detach "${parent}"
                fi
        done
}

load_rc_config $name
run_rc_command "$1"