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@lists.ubuntu.com
https://lists.ubuntu.com/mailman/listinfo/ubuntu-bugs

Reply via email to