#!/bin/sh # # Standard initramfs preamble # prereqs() { # Make sure that cryptroot is run last in local-top for req in /scripts/local-top/*; do script=${req##*/} if [ $script != cryptroot ]; then echo $script fi done } case $1 in prereqs) prereqs exit 0 ;; esac # # Helper functions # message() { if [ -p /dev/.initramfs/usplash_outfifo ] && [ -x /sbin/usplash_write ]; then usplash_write "TEXT-URGENT $@" else echo "$@" >&2 fi return 0 } parse_options() { local cryptopts cryptopts="$1" if [ -z "$cryptopts" ]; then return 1 fi # Defaults cryptcipher=aes-cbc-essiv:sha256 cryptsize=256 crypthash=ripemd160 crypttarget=cryptroot cryptsource="" cryptlvm="" cryptkeyscript="" cryptkey="" # This is only used as an argument to an eventual keyscript crypttries=3 local IFS=" ," for x in $cryptopts; do case $x in hash=*) crypthash=${x#hash=} ;; size=*) cryptsize=${x#size=} ;; cipher=*) cryptcipher=${x#cipher=} ;; target=*) crypttarget=${x#target=} ;; source=*) cryptsource=${x#source=} if [ ${cryptsource#UUID=} != $cryptsource ]; then cryptsource="/dev/disk/by-uuid/${cryptsource#UUID=}" elif [ ${cryptsource#LABEL=} != $cryptsource ]; then cryptsource="/dev/disk/by-label/${cryptsource#LABEL=}" fi ;; lvm=*) cryptlvm=${x#lvm=} ;; keyscript=*) cryptkeyscript=${x#keyscript=} ;; key=*) if [ "${x#key=}" != "none" ]; then cryptkey=${x#key=} fi ;; tries=*) crypttries="${x#tries=}" case "$crypttries" in *[![:digit:].]*) crypttries=3 ;; esac ;; esac done if [ -z "$cryptsource" ]; then message "cryptsetup: source parameter missing" return 1 fi return 0 } activate_vg() { local vg vg="${1#/dev/mapper/}" # Sanity checks if [ ! -x /sbin/lvm ] || [ "$vg" = "$1" ]; then return 1 fi # Make sure that the device contains at least one dash if [ "${vg%%-*}" = "$vg" ]; then return 1 fi # Split volume group from logical volume. vg=$(echo ${vg} | sed -e 's#\(.*\)\([^-]\)-[^-].*#\1\2#') # Reduce padded --'s to -'s vg=$(echo ${vg} | sed -e 's#--#-#g') lvm vgchange -ay ${vg} return $? } activate_evms() { local dev module dev="${1#/dev/evms/}" # Sanity checks if [ ! -x /sbin/evms_activate ] || [ "$dev" = "$1" ]; then return 1 fi # Load modules used by evms for module in dm-mod linear raid0 raid1 raid10 raid5 raid6; do /sbin/modprobe -q $module done # Activate it /sbin/evms_activate return $? } setup_mapping() { local opts count cryptcreate cryptremove NEWROOT opts="$1" if [ -z "$opts" ]; then return 0 fi parse_options "$opts" || return 1 if [ -n "$cryptkeyscript" ] && [ ! -x "$cryptkeyscript" ]; then message "cryptsetup: error - script \"$cryptkeyscript\" missing" return 1 fi # The same target can be specified multiple times # e.g. root and resume lvs-on-lvm-on-crypto if [ -e "/dev/mapper/$crypttarget" ]; then return 0 fi /sbin/modprobe -q dm_crypt # Make sure the cryptsource device is available if [ ! -e $cryptsource ]; then activate_vg $cryptsource activate_evms $cryptsource fi /sbin/udevadm settle --timeout=30 if [ ! -e $cryptsource ]; then message "cryptsetup: source device $cryptsource not found" return 1 fi # Prepare commands if /sbin/cryptsetup isLuks $cryptsource > /dev/null 2>&1; then cryptcreate="/sbin/cryptsetup -T 1 luksOpen $cryptsource $crypttarget" else cryptcreate="/sbin/cryptsetup -T 1 -c $cryptcipher -s $cryptsize -h $crypthash create $crypttarget $cryptsource" fi cryptremove="/sbin/cryptsetup remove $crypttarget" NEWROOT="/dev/mapper/$crypttarget" # Try to get a satisfactory password $crypttries times count=0 while [ $crypttries -le 0 ] || [ $count -lt $crypttries ]; do count=$(( $count + 1 )) if [ $count -gt 1 ]; then sleep 3 fi if [ $crypttries -gt 0 ] && [ $count -gt $crypttries ]; then message "cryptsetup: maximum number of tries exceeded for $crypttarget" return 1 fi if [ -z "$cryptkeyscript" ]; then cryptkeyscript="/lib/cryptsetup/askpass" cryptkey="Enter passphrase to unlock the disk $cryptsource ($crypttarget): " fi if ! crypttarget="$crypttarget" cryptsource="$cryptsource" \ $cryptkeyscript "$cryptkey" | $cryptcreate --key-file=- ; then message "cryptsetup: cryptsetup failed, bad password or options?" continue fi if [ ! -e "$NEWROOT" ]; then message "cryptsetup: unknown error setting up device mapping" return 1 fi FSTYPE='' eval $(fstype < "$NEWROOT") # See if we need to setup lvm on the crypto device if [ "$FSTYPE" = "lvm" ] || [ "$FSTYPE" = "lvm2" ]; then if [ -z "$cryptlvm" ]; then message "cryptsetup: lvm fs found but no lvm configured" return 1 elif ! activate_vg "/dev/mapper/$cryptlvm"; then message "cryptsetup: failed to setup lvm device" return 1 fi NEWROOT="/dev/mapper/$cryptlvm" eval $(fstype < "$NEWROOT") fi if [ -z "$FSTYPE" ] || [ "$FSTYPE" = "unknown" ]; then message "cryptsetup: unknown fstype, bad password or options?" $cryptremove continue fi message "cryptsetup: $crypttarget setup successfully" break done /sbin/udevadm settle --timeout=30 return 0 } # # Begin real processing # # Do we have any kernel boot arguments? found='' for opt in $(cat /proc/cmdline); do case $opt in cryptopts=*) found=yes setup_mapping "${opt#cryptopts=}" ;; esac done if [ -n "$found" ]; then exit 0 fi # Do we have any settings from the /conf/conf.d/cryptroot file? if [ -r /conf/conf.d/cryptroot ]; then while read mapping <&3; do setup_mapping "$mapping" done 3< /conf/conf.d/cryptroot fi exit 0