FIX FOR BOTH HARDY AND JAUNTY: Some time back, I modified /lib/cnryptsetup/cryptdisks.functions to make Usplash work to mount a non-root LUKS partition in Hardy. The working principle is this: On b oth my AMD 64 single core and my Intel Atom, if you type the passphrase with Usplash running while cryptsetup is waiting for it, it goes right to cryptsetup same as if the console was showing, though there would be no prompt to tell you when to type it! This altered code drops the usplash_write "quit" line from Hardy's version, and uses Usplash_write's VERBOSE and TEXT functions to prompt just before cryptsetup runs-but does NOT try to use anything like askpass or usplash_write_inputquiet due to bugs. Since the Jaunty version leaves the password on the console, I must assume it would be easier for an attacker to scan all memory and recognize the password than it would be to recognize the actual key. This is unacceptable, so I have rolled back to my own code. Here's the new cryptdisks.functions Cut and paste into gedit, etc and save as /lib/cryptdisks.functions as root after backing up the original file: ########################################################## # # This file is for inclusion with # . /lib/cryptsetup/cryptdisks.functions # and should not be executed directly. PATH="/sbin:/bin" TABFILE=/etc/crypttab CRYPTDISKS_ENABLE="Yes" #set -x # Sanity checks [ -x /sbin/cryptsetup ] || exit 0 [ -f "$TABFILE" ] || exit 0 . /lib/lsb/init-functions if [ -r /etc/default/cryptdisks ]; then . /etc/default/cryptdisks fi MOUNT="$CRYPTDISKS_MOUNT" case "$CRYPTDISKS_ENABLE" in [Nn]*) exit 0 ;; esac # Always output to console stdin=`readlink /proc/self/fd/0` if [ "${stdin#/dev/null}" != "$stdin" ] && [ "$ON_VT" != "yes" ]; then exec env ON_VT=yes /usr/bin/openvt -f -c `fgconsole` -w $0 "$@" fi # Parses the option field from the crypttab file parse_opts () { local opts opt IFS PARAM VALUE opts="$1" LOUD="" PARAMS="" CHECK="" CHECKARGS="" PRECHECK="" TRIES="3" MAKETMP="" MAKESWAP="" USELUKS="" TIMEOUT="" KEYSCRIPT="" # Parse the options field, convert to cryptsetup parameters # and construct the command line IFS=',' for opt in $opts; do PARAM=$(echo "$opt" | sed 's/=.*//') VALUE=$(echo "$opt" | sed '/=/!d;s/^.*=//') case "$PARAM" in readonly) PARAMS="$PARAMS -r" ;; cipher) if [ -z "$VALUE" ]; then log_warning_msg "$dst: no value for cipher option, skipping" return 1 fi PARAMS="$PARAMS -c $VALUE" ;; size) if [ -z "$VALUE" ]; then log_warning_msg "$dst: no value for size option, skipping" return 1 fi PARAMS="$PARAMS -s $VALUE" ;; hash) if [ -z "$VALUE" ]; then log_warning_msg "$dst: no value for hash option, skipping" return 1 fi PARAMS="$PARAMS -h $VALUE" ;; verify) PARAMS="$PARAMS -y" ;; check) if [ -z "$VALUE" ]; then VALUE="$CRYPTDISKS_CHECK" fi if [ -x "$VALUE" ]; then CHECK="$VALUE" elif [ -x "/lib/cryptsetup/checks/$VALUE" ]; then CHECK="/lib/cryptsetup/checks/$VALUE" else log_warning_msg "check $VALUE is not an executable script, skipping" return 1 fi ;; checkargs) if [ -n "$VALUE" ]; then CHECKARGS="$VALUE" fi ;; precheck) if [ -z "$VALUE" ]; then VALUE="$CRYPTDISKS_PRECHECK" fi if [ -x "$VALUE" ]; then PRECHECK="$VALUE" elif [ -x "/lib/cryptsetup/checks/$VALUE" ]; then PRECHECK="/lib/cryptsetup/checks/$VALUE" else log_warning_msg "precheck $VALUE is not an executable script, skipping" return 1 fi ;; tries) if echo "$VALUE" | grep -q "^[[:digit:]]\+$" && [ "$VALUE" -gt 0 ]; then TRIES="$VALUE" else log_warning_msg "$dst: option tries used with an incorrect argument - forced to $TRIES" fi PARAMS="$PARAMS --tries=$TRIES" ;; timeout) if [ -z "$VALUE" ]; then TIMEOUT="$CRYPTDISKS_TIMEOUT" elif echo "$VALUE" | grep -q "^[[:digit:]]\+$"; then TIMEOUT="$VALUE" else log_warning_msg "$dst: option timeout used with an incorrect argument - forced to '$TIMEOUT'" fi PARAMS="$PARAMS --timeout=$TIMEOUT" ;; swap) MAKESWAP=yes SWCHECK="/lib/cryptsetup/checks/un_vol_id" SWCHECKARGS="swap" ;; tmp) MAKETMP=yes ;; luks) USELUKS=yes ;; loud) LOUD=yes ;; keyscript) if [ -n "$KEYSCRIPT" ]; then log_warning_msg "$dst: multiple key decryption options are not allowed together, skipping" return 1 elif [ -z "$VALUE" ]; then log_warning_msg "$dst: no value for keyscript option, skipping" return 1 fi KEYSCRIPT="$VALUE" ;; esac done return 0 } # Set up loopback devices lo_setup () { local loopdev if [ ! -f "$src" ]; then return 0 fi if [ ! -x /sbin/losetup ]; then return 1 fi if ! grep -q "[[:space:]]loop$" /proc/devices; then modprobe -qb loop > /dev/null 2>&1 || return 1 fi loopdev=$(losetup -f 2> /dev/null) || return 1 losetup "$loopdev" "$src" || return 1 src="$loopdev" return 0 } # Sanity check for keys check_key () { local GMODE OMODE OWNER GROUP # If the keyscript option is set, the "key" is just an argument to # the keyscript and not necessarily a file if [ -n "$KEYSCRIPT" ]; then return 0 fi if [ -z "$key" ] || [ "$key" = "none" ]; then INTERACTIVE="yes" return 0 fi INTERACTIVE="no" if [ ! -e "$key" ]; then log_warning_msg "$dst: keyfile not found" return 1 fi # stat is unfortunately in /usr/bin... OMODE=$(ls -l "$key" | sed 's/[[:space:]].*//;s/^.\{7\}//') GMODE=$(ls -l "$key" | sed 's/[[:space:]].*//;s/^.\{4\}\(.\{3\}\).*/\1/') GROUP=$(ls -l "$key" | sed 's/^.\{11\}[^[:space:]]* [^[:space:]]* \([^[:space:]]*\).*/\1/') OWNER=$( ls -l "$key" | sed 's/^.\{11\}[^[:space:]]* \([^[:space:]]*\).*/\1/') # LUKS requires a persistent key, /dev/*random is not supported if [ "$USELUKS" = "yes" ] && [ "$key" != "${key%random}" ]; then log_warning_msg "$dst: LUKS does not work with random data as key" return 1 fi # Check owner if [ "$OWNER" != "root" ]; then log_warning_msg "$dst: INSECURE OWNER FOR $key, see /usr/share/doc/cryptsetup/README.Debian." fi # If key is random, we're done if [ "$key" != "${key%random}" ]; then return 0 fi # Check group and other permissions if [ "$OMODE" != "---" ] || [ "$GROUP" != "root" ] && [ "$GMODE" != "---" ]; then log_warning_msg "$dst: INSECURE MODE FOR $key, see /usr/share/doc/cryptsetup/README.Debian." fi return 0 } # Setup a luks mapping do_luks () { local tried tried=0 if ! cryptsetup isLuks "$src" >/dev/null 2>&1; then log_warning_msg "$dst: device '$src' is not a LUKS partition, skipping" return 1 fi if [ -n "$KEYSCRIPT" ]; then PARAMS="$PARAMS --key-file=-" while [ "$tried" -lt "$TRIES" ]; do if "$KEYSCRIPT" "$key" <&1 | cryptsetup $PARAMS luksOpen "$src" "$dst"; then break fi tried=$(( $tried + 1 )) done elif [ "$INTERACTIVE" != "yes" ]; then PARAMS="$PARAMS --key-file=$key" while [ "$tried" -lt "$TRIES" ]; do if cryptsetup $PARAMS luksOpen "$src" "$dst" <&1; then break fi tried=$(( $tried + 1 )) done else if test "x$INTERACTIVE" != "xyes" ; then PARAMS="$PARAMS --key-file=$key" cryptsetup $PARAMS luksOpen $src $dst <&1 else ##### # BEGIN LOCAL CHANGE######################################################################## #if [ -x /sbin/usplash_write -a -p /dev/.initramfs/usplash_outfifo ]; then # /sbin/usplash_write "QUIT" # # saftey sleep ! # sleep 2 #fi ## prompt through Usplash for password usplash_write "VERBOSE on" usplash_write "CLEAR" usplash_write "TIMEOUT 0" usplash_write "TEXT Enter LUKS Passphrase,Ret 3x to ignore encrypted volume" cryptsetup $PARAMS luksOpen $src $dst <&1 ##This line from original scritp### usplash_write "SUCCESS OK" usplash_write "TEXT key slot 0 unlocked: Encrypted Filesystem in us" usplash_write "VERBOSE default" ##### # END LOCAL CHANGE ########################################################################### fi fi if [ "$tried" -ge "$TRIES" ]; then return 1 fi if [ -n "$CHECK" ] && ! "$CHECK" "/dev/mapper/$dst" $CHECKARGS; then log_warning_msg "$dst: the check for '/dev/mapper/$dst' failed" cryptsetup luksClose $dst return 1 fi return 0 } # Setup a regular mapping do_noluks () { local pre_out tried tried=0 if [ -z "$PRECHECK" ]; then PRECHECK="/lib/cryptsetup/checks/un_vol_id" fi if ! pre_out=$("$PRECHECK" "$src" 2> /dev/null) && \ [ "$MAKESWAP" != "yes" ] && \ ! /lib/cryptsetup/checks/vol_id "$src" swap >/dev/null; then log_warning_msg "$dst: the precheck for '$src' failed: $pre_out" return 1 fi if [ -n "$KEYSCRIPT" ]; then PARAMS="$PARAMS --key-file=-" elif [ "$INTERACTIVE" != "yes" ]; then PARAMS="$PARAMS --key-file=$key" fi while [ "$tried" -lt "$TRIES" ]; do if [ -n "$KEYSCRIPT" ]; then "$KEYSCRIPT" "$key" <&1 | cryptsetup $PARAMS create "$dst" "$src" else cryptsetup $PARAMS create "$dst" "$src" <&1 fi if [ -z "$CHECK" ] || "$CHECK" "/dev/mapper/$dst" $CHECKARGS; then break else log_warning_msg "$dst: the check for '/dev/mapper/$dst' failed - maybe the password is wrong" cryptsetup remove "$dst" fi tried=$(( $tried + 1 )) done if [ "$tried" -ge "$TRIES" ]; then return 1 fi return 0 } # Premounts file systems mount_fs () { local point MOUNTED="" for point in $MOUNT; do if mount "$point" >/dev/null; then MOUNTED="$MOUNTED $point" fi done } # Postunmounts file systems umount_fs () { local point for point in $MOUNTED; do umount "$point" >/dev/null done } # Prepares swap partitions using random keys do_swap () { local swap_out if [ "$MAKESWAP" != "yes" ] || [ ! -b "/dev/mapper/$dst" ]; then return 0 fi if swap_out=$(/lib/cryptsetup/checks/un_vol_id "/dev/mapper/$dst" 2> /dev/null) || \ /lib/cryptsetup/checks/vol_id "/dev/mapper/$dst" swap > /dev/null 2>&1; then mkswap "/dev/mapper/$dst" > /dev/null 2>&1 else log_warning_msg "$dst: the check for '/dev/mapper/$dst' failed. /dev/mapper/$dst contains data: $swap_out" do_close return 1 fi return 0 } # Prepares tmp partitions using random keys do_tmp () { if [ "$MAKETMP" != "yes" ] || [ ! -b "/dev/mapper/$dst" ]; then return 0 fi mke2fs "/dev/mapper/$dst" > /dev/null 2>&1 || return 1 mount -t ext2 "/dev/mapper/$dst" /tmp || return 1 chmod 1777 /tmp umount /tmp return 0 } # Removes a mapping do_close () { local found IFS opt found="no" IFS=',' for opt in $opts; do if [ "$opt" = "luks" ]; then found="yes" break fi done if [ "$found" = "yes" ]; then cryptsetup luksClose "$dst" else cryptsetup remove "$dst" fi return $? } load_optimized_aes_module () { local asm_module modulesdir # find directory with kernel modules modulesdir="/lib/modules/`uname -r`" # Add assembly optimized AES module if it exists asm_module=`ls -1 "$modulesdir"/kernel/arch/*/*/aes*.ko` if [ $asm_module ];then insmod $asm_module 2>/dev/null || true fi } # Sets up all entries in crypttab do_start () { local dst src key opts result modprobe -qb dm-mod || true modprobe -qb dm-crypt || true dmsetup mknodes > /dev/null 2>&1 || true log_action_begin_msg "Starting $INITSTATE crypto disks" load_optimized_aes_module mount_fs egrep -v "^[[:space:]]*(#|$)" "$TABFILE" | while read dst src key opts; do # Make sure that all fields are present if [ -z "$dst" ]; then continue elif [ -z "$src" ] || [ -z "$key" ] || [ -z "$opts" ]; then device_msg "$dst" "skipped, missing parameters" continue fi # parse UUID= symlinks if [ ${src#UUID=} != $src ]; then src="/dev/disk/by-uuid/${src#UUID=}" elif [ ${src#LABEL=} != $src ]; then src="/dev/disk/by-label/${src#LABEL=}" fi # Make sure source device exists if [ ! -r "$src" ]; then if [ "$LOUD" = "yes" ]; then device_msg "$dst" "skipped, device $src does not exist" fi continue fi # Make sure that target device doesn't exist if [ -b "/dev/mapper/$dst" ]; then device_msg "$dst" "running" continue fi # All checks passed, do the preparatory steps if ! parse_opts "$opts"; then device_msg "$dst" "invalid opts" continue elif ! check_key; then device_msg "$dst" "invalid key" continue elif ! lo_setup; then device_msg "$dst" "loopback failed" fi # Do the real setup log_progress_msg "$dst (starting)" result="ok" if [ "$USELUKS" = "yes" ]; then do_luks || result="fail" else do_noluks || result="fail" fi # Finish up if [ "$result" != "ok" ]; then log_progress_msg "$dst (failed)" else do_swap do_tmp log_progress_msg "$dst (started)" fi done umount_fs log_action_end_msg 0 } # Removes all mappings in crypttab do_stop () { local dst src key opts opencount major minor loopmajor dmsetup mknodes log_action_begin_msg "Stopping $INITSTATE crypto disks" loopmajor=$(grep "[[:space:]]*loop$" /proc/devices | sed 's/^[[:space:]]*//;s/[[:space:]].*//') egrep -v "^[[:space:]]*(#|$)" "$TABFILE" | while read dst src key opts; do if [ ! -b "/dev/mapper/$dst" ]; then device_msg "$dst" "stopped" continue fi opencount=$(dmsetup info -c --noheadings -o open "$dst" 2> /dev/null) if [ -z "$opencount" ]; then device_msg "$dst" "error" continue elif [ "$opencount" != "0" ]; then device_msg "$dst" "busy" continue fi major=$(dmsetup info -c --noheadings -o major "$dst" 2> /dev/null) minor=$(dmsetup info -c --noheadings -o minor "$dst" 2> /dev/null) if [ -z "$major" ] || [ -z "$minor" ]; then device_msg "$dst" "error" continue fi do_close log_action_cont_msg "$dst (stopping)" # Detach loopback device, if attached if [ -f "$src" ] && [ -n "$loopmajor" ] && [ "$loopmajor" = "$major" ]; then losetup -d "/dev/loop$minor" > /dev/null 2>&1 || true fi done log_action_end_msg 0 } # Convenience function to handle $VERBOSE device_msg () { local dst msg dst="$1" msg="$2" if [ "$VERBOSE" != "no" ]; then log_action_cont_msg "$dst ($msg)" fi }