This is the latest and greatest version of the script with the previous fixes applied and a /dev/console redirection also added for the eventual cryptgetpw script.

I'll reattach this later as a proper patch to cryptsetup instead of just the two additional files...

Re,
David



#!/bin/sh

PREREQ=""

prereqs()
{
        echo "$PREREQ"
}

case $1 in
prereqs)
        prereqs
        exit 0
        ;;
esac

. /usr/share/initramfs-tools/hook-functions

find_root_device() {
        [ -r /etc/fstab ] || return

        grep '^[^#]' /etc/fstab | ( \
        while read device mount type options dump pass; do
                if [ "$mount" = "/" ]; then
                        echo "$device"
                        return
                fi
        done )
}

get_root_opts() {
        local node rootopts
        node=$1

        [ -z $node ] && return
        [ -r /etc/crypttab ] || return

        rootopts=$( grep ^$node /etc/crypttab | \
                    head -1 | sed 's/[[:space:]]+*/ /g' | cut -d " " -f 4-)
        echo "$rootopts"
        [ ! -z $rootopts ] || return 1
        return 0
}

get_root_modules() {
        local rootopts
        rootopts=$1

        [ ! -z $rootopts ] || return

        echo "dm_mod"
        echo "dm_crypt"
        local IFS=", "
        for opt in $rootopts; do
                # Does option start with cipher=?
                value=${opt#cipher=}
                [ $value != $opt ] || continue

                # Add the cipher to the list of modules
                cipher=${value%%-*}
                echo $cipher

                # Possibly add a hash as well
                hash=${value##*:}
                [ ! -z $hash -o $hash != $value ] || continue
                echo $hash
        done
}

get_root_initramfsopts() {
        local rootnode rootopts
        rootnode=$1
        rootopts=$2

        [ ! -z $rootnode ] || return
        [ ! -z $rootopts ] || return

        echo -n "node=$rootnode"
        local IFS=", "
        for opt in $rootopts; do
                case $opt in
                        cipher=*)
                                echo -n ",$opt"
                                ;;
                        hash=*)
                                echo -n ",$opt"
                                ;;
                        size=*)
                                echo -n ",$opt"
                                ;;
                        *)
                                # Presumably a non-supported option
                                ;;
                esac
        done
        echo ""
}

# Find out which device root is on
rootdev=$(find_root_device)
[ ! -z $rootdev ] || exit 0

# Check that it is a node under /dev/mapper/
node=${rootdev#/dev/mapper/}
[ "$node" != $rootdev ] || exit 0

# Get crypttab root options
rootopts=$(get_root_opts $node $opts)
[ ! -z $rootopts ] || exit 0

# Calculate needed modules
modules=$(get_root_modules $rootopts | sort | uniq)
for x in $modules; do
        force_load ${x}
done

# Check the root options to write to the initramfs
initramfsopts=$(get_root_initramfsopts $node $rootopts)
echo "CRYPTOPTS=\"$initramfsopts\"" > ${DESTDIR}/conf/conf.d/cryptroot

copy_exec /sbin/cryptsetup /sbin
copy_exec /sbin/dmsetup /sbin
[ -x "/etc/mkinitramfs/cryptgetpw" ] && copy_exec /etc/mkinitramfs/cryptgetpw 
/sbin

exit 0
#!/bin/sh

PREREQ=""

prereqs()
{
        echo "$PREREQ"
}

case $1 in
# get pre-requisites
prereqs)
        prereqs
        exit 0
        ;;
esac

# Do we have any settings from the /conf/conf.d/cryptroot file?
[ -r /conf/conf.d/cryptroot ] && . /conf/conf.d/cryptroot
cryptopts="${CRYPTOPTS}"

# Does the kernel boot command line override them?
for x in $(cat /proc/cmdline); do
        case $x in
        cryptopts=*)
                cryptopts=${x#cryptopts=}
                ;;
        esac
done

# Sanity checks
eval $(fstype < ${ROOT})
if [ "$FSTYPE" != "luks" -a -z "$cryptopts" ]; then
        # Apparently the root partition isn't encrypted
        echo "No cryptoroot configured or detected"
        exit 0
fi

# There are two possible scenarios here:
#
# 1) The fstype of the root device has been identified as "luks"
# 2) The fstype is not "luks" but cryptopts has been set
#
# The former means that we use the luks functionality of cryptsetup, the
# latter means that we do it the old-fashioned way.

# Start by parsing some options, all options are relevant to regular cryptsetup
# but only cryptnode is relevant to luks which picks up the rest of the 
# parameters by reading the partition header
cryptcipher=aes-cbc-essiv:sha256
cryptsize=256
crypthash=sha256
cryptnode=cryptroot
if [ -n "$cryptopts" ]; then
        IFS=" ,"
        for x in $cryptopts; do
                case $x in
                hash=*)
                        crypthash=${x#hash=}
                        ;;
                size=*)
                        cryptsize=${x#size=}
                        ;;
                cipher=*)
                        cryptcipher=${x#cipher=}
                        ;;
                node=*)
                        cryptnode=${x#node=}
                        ;;
                esac
        done
        unset IFS
fi
NEWROOT="/dev/mapper/$cryptnode"

# Check which cryptosolution we want
if [ "$FSTYPE" = "luks" ]; then
        # 1) The fstype of the root device has been identified as "luks"
        cryptcreate="/sbin/cryptsetup luksOpen $ROOT $cryptnode"
        cryptremove=""
else
        # 2) The fstype is not "luks" but cryptopts have been set
        cryptcreate="/sbin/cryptsetup -c $cryptcipher -s $cryptsize -h 
$crypthash create $cryptnode $ROOT"
        cryptremove="/sbin/cryptsetup remove $cryptnode"
fi

# Loop until we have a satisfactory password
while [ 1 ]; do
        if [ -x "/sbin/cryptgetpw" ]; then
                /sbin/cryptgetpw < /dev/console | $cryptcreate
        else
                $cryptcreate < /dev/console
        fi

        if [ $? -eq 0 ]; then
                fstype < "$NEWROOT" > /dev/.initramfs/source.me
                if [ $? -eq 0 ]; then
                        . /dev/.initramfs/source.me
                        if [ "$FSTYPE" != "unknown" ]; then
                                break
                        fi
                fi
        fi

        echo "$0: cryptsetup failed or fstype not recognized, bad password or 
options?"
        $cryptremove
        sleep 3
done

# init can now pick up new FSTYPE, FSSIZE and ROOT
echo "ROOT=\"$NEWROOT\"" >> /dev/.initramfs/source.me

exit 0

Reply via email to