[Bug 55159] Re: usplash prevents passwords from being not echoed on the console
Luke
lukekuhn at hotmail.com
Thu Apr 9 14:26:37 UTC 2009
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
}
** Attachment added: "Alternate /lib/cryptsetup/cryptdisks.functions"
http://launchpadlibrarian.net/25113038/cryptdisks.functions
--
usplash prevents passwords from being not echoed on the console
https://bugs.launchpad.net/bugs/55159
You received this bug notification because you are a member of Ubuntu
Bugs, which is subscribed to Ubuntu.
--
ubuntu-bugs mailing list
ubuntu-bugs at lists.ubuntu.com
https://lists.ubuntu.com/mailman/listinfo/ubuntu-bugs
More information about the universe-bugs
mailing list