--- cryptdisks.functions.orig 2007-01-06 22:53:18.000000000 +0100 +++ cryptdisks.functions 2007-01-06 22:51:54.000000000 +0100 @@ -10,13 +10,25 @@ test -x $DEVMAPCMD || exit 0 test -f $TABFILE || exit 0 -# Always output to console +# check if usplash is running. if so, do not attach to the console. +# because all i/o including the entered password would be echoed plain text! +pgrep usplash + +if [ $? -gt 0 ]; then + USPLASH_RUNNING="false" +else + USPLASH_RUNNING="true" +fi + stdin=`readlink /proc/self/fd/0` -if [ "${stdin#/dev/null}" != "$stdin" ]; then - exec /dev/console 2>&1 +if [ "${stdin#/dev/null}" != "$stdin" ] && [ "$ON_VT" != "yes" ] && [ "$USPLASH_RUNNING != "yes ]; then + exec env ON_VT=yes /usr/bin/openvt -f -c `fgconsole` -w $0 "$@" fi parse_opts () { + local opts="$1" + + LOUD="" PARAMS="" CHECK="" CHECKARGS="" @@ -25,17 +37,15 @@ MAKETMP="" MAKESWAP="" USELUKS="" - SKIP="" TIMEOUT="" - SSL="" - GPG="" + KEYSCRIPT="" # Parse the options field, convert to cryptsetup parameters # and construct the command line - while test "x$opt" != "x" ; do - ARG=`echo $opt | sed "s/,.*//"` - opt=${opt##$ARG} - opt=${opt##,} + while test "x$opts" != "x" ; do + ARG=`echo $opts | sed "s/,.*//"` + opts=${opts##$ARG} + opts=${opts##,} PARAM=`echo $ARG | sed "s/=.*//"` case "$ARG" in @@ -56,22 +66,22 @@ cipher) PARAMS="$PARAMS -c $VALUE" if test "x$VALUE" = "x" ; then - echo -e "\n - no value for cipher option, skipping" >&2 - SKIP="yes" + echo "no value for cipher option, skipping" >&2 + return 1 fi ;; size) PARAMS="$PARAMS -s $VALUE" if test "x$VALUE" = "x" ; then - echo -e "\n - no value for size option, skipping" >&2 - SKIP="yes" + echo "no value for size option, skipping" >&2 + return 1 fi ;; hash) PARAMS="$PARAMS -h $VALUE" if test "x$VALUE" = "x" ; then - echo -e "\n - no value for hash option, skipping" >&2 - SKIP=yes + echo "no value for hash option, skipping" >&2 + return 1 fi ;; verify) @@ -114,7 +124,7 @@ [0-9]*) ;; *) - echo -e "\n - option TRIES is wrongly set to $TRIES - forced to '3' " >&2 + echo "option TRIES is wrongly set to $TRIES - forced to '3' " >&2 TRIES="3" ;; esac @@ -130,7 +140,7 @@ [0-9]*) ;; *) - echo -e "\n - option TIMEOUT is wrongly set to $TIMEOUT - forced to '0' " >&2 + echo "option TIMEOUT is wrongly set to $TIMEOUT - forced to '0' " >&2 TIMEOUT="0" ;; esac @@ -151,190 +161,201 @@ LOUD=yes ;; ssl) - SSL=yes + if [ -n "$KEYSCRIPT" ]; then + echo "multiple key decryption options are not allowed together, skipping" >&2 + return 1 + fi + KEYSCRIPT="/lib/cryptsetup/scripts/decrypt_old_ssl" ;; gpg) - GPG=yes + if [ -n "$KEYSCRIPT" ]; then + echo "multiple key decryption options are not allowed together, skipping" >&2 + return 1 + fi + KEYSCRIPT="/lib/cryptsetup/scripts/decrypt_gpg" ;; + keyscript) + if [ -n "$KEYSCRIPT" ]; then + echo "multiple key decryption options are not allowed together, skipping" >&2 + return 1 + elif test "x$VALUE" = "x" ; then + echo "no value for keyscript option, skipping" >&2 + return 1 + fi + KEYSCRIPT="$VALUE" + ;; esac done - if [ "$SSL" != "" -a "$GPG" != "" ]; then - echo -e "\n - ssl and gpg options are not allowed together, skipping" >&2 - continue - fi - - if test "x$SKIP" = "xyes" ; then - continue - fi + return 0 } -decrypt_ssl () { - origumask=`umask` - umask 077 - tmpkey=`tempfile` +lo_setup () { + local LOOP_ID="" - while ( ! /usr/bin/openssl enc -aes256 -d -salt -in $key -out $tmpkey \ - -k $password > /dev/null 2>&1 ); do - echo -en "\nSecond password for key $key: " - read -s password - echo - [ "$password" = "" ] && return 0 - done + # Set up loopback devices + if [ ! -f "$src" ]; then + return 0 + fi - deckey=`tempfile` - while ( ! /usr/bin/openssl dsa -in $tmpkey -out $deckey -passin \ - pass:$password > /dev/null 2>&1 ); do - echo -en "\nFirst password for key $key: " - read -s password - echo - [ "$password" = "" ] && return 0 - done + if [ ! -d "/sys/block/loop0" ]; then + modprobe loop || return 1 + fi - password="" - rm -f $tmpkey && tmpkey="" - umask $origumask -} - -decrypt_gpg () { - origumask=`umask` - umask 077 - deckey=`tempfile` - - echo -e "\n - gpg option is not implemented yet, skipping" >&2 - continue - - while ( ! echo $password | /usr/bin/gpg --passphrase-fd 0 -o $deckey \ - --decrypt $key >/dev/null 2>&1 ); do - echo -en "\nPassphrase for key $key: " - read -s password - echo - [ "$password" = "" ] && return 0 + for i in 0 1 2 3 4 5 6 7 ; do + if [ "$(cat /sys/block/loop$i/size)" -eq 0 ]; then + LOOP_ID=$i + break + fi done - - password="" - umask $origumask -} -lo_setup () { - # Set up loopback devices - if test -f "$src" ; then - test -d /sys/block/loop0 || modprobe loop || continue - LOOP_ID= - for i in 0 1 2 3 4 5 6 7 ; do - if test "x`cat /sys/block/loop$i/size`" = "x0" ; then - LOOP_ID=$i - break - fi - done - if test "x$LOOP_ID" = "x" ; then - continue - else - $LOSETUP /dev/loop$LOOP_ID $src || continue - src=/dev/loop$LOOP_ID - fi + if [ -z "$LOOP_ID" ]; then + return 1 fi + + $LOSETUP /dev/loop$LOOP_ID $src || return 1 + src=/dev/loop$LOOP_ID + return 0 } check_key () { - if [ "x$key" != "x" ] && [ "x$key" != "xnone" ]; then - INTERACTIVE="no" - if test -e "$key" ; then - MODE=`ls -l $key | sed 's/^....\(......\).*/\1/'` - OWNER=`ls -l $key | sed 's/^[^ ]* *[^ ]* *\([^ ]*\).*/\1/'` - - # luks requires a persistent key, /dev/*random is not supported - if test "x$USELUKS" = "xyes"; then - if test "$key" = "/dev/urandom" || \ - test "$key" = "/dev/hwrandom" || \ - test "$key" = "/dev/random"; then - echo -e "\n - LUKS does not work with random data as key, skipping" >&2 - continue - fi - fi - if test "$MODE" != "------" && \ - test "$key" != "/dev/urandom" && \ - test "$key" != "/dev/hwrandom" && \ - test "$key" != "/dev/random"; then - echo -e "\n - INSECURE MODE FOR $key" >&2 - fi - if test $OWNER != root; then - echo -e "\n - INSECURE OWNER FOR $key" >&2 - fi - else - echo -e "\n - Keyfile for '$dst' not found, skipping" >&2 - continue - fi - if [ "x$SSL" = "xyes" ]; then - if [ -x /usr/bin/openssl ]; then - decrypt_ssl && key=$deckey - else - echo -e "\n - Openssl isnot available, skipping" >&2 - continue - fi - elif [ "x$GPG" = "xyes" ]; then - if [ -x /usr/bin/gnupg ]; then - decrypt_gpg && key=$deckey - else - echo -e "\n - Gnupg is not available, skipping" >&2 - continue - fi - fi - else + # 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" echo "" + return 0 + fi + + if [ ! -e "$key" ]; then + echo "Keyfile for '$dst' not found, skipping" >&2 + return 1 + fi + + # FIXME: Use stat here instead + MODE=`ls -l $key | sed 's/^....\(......\).*/\1/'` + OWNER=`ls -l $key | sed 's/^[^ ]* *[^ ]* *\([^ ]*\).*/\1/'` + + # LUKS requires a persistent key, /dev/*random is not supported + if [ "$USELUKS" = "yes" ] && [ "$key" != "${key%random}" ]; then + echo "LUKS does not work with random data as key, skipping" >&2 + return 1 fi + + if [ "$key" = "${key%random}" ] && [ "$MODE" != "------" ]; then + echo "INSECURE MODE FOR $key, see /usr/share/doc/cryptsetup/README.Debian." >&2 + # don't break here for now + # return 1 + fi + + if [ "$OWNER" != "root" ]; then + echo "INSECURE OWNER FOR $key, see /usr/share/doc/cryptsetup/README.Debian." >&2 + # don't break here for now + # return 1 + fi + + INTERACTIVE="no" + return 0 } do_luks () { - if $CRYPTCMD isLuks $src >/dev/null 2>&1; then + if ! $CRYPTCMD isLuks $src >/dev/null 2>&1; then + echo "Device '$src' is not a LUKS partition, skipping" >&2 + return 1 + fi + + if test "x$KEYSCRIPT" != "x" ; then + PARAMS="$PARAMS --key-file=-" + $KEYSCRIPT $key <&1 | $CRYPTCMD $PARAMS luksOpen $src $dst + else if test "x$INTERACTIVE" != "xyes" ; then PARAMS="$PARAMS --key-file=$key" - fi - $CRYPTCMD $PARAMS luksOpen $src $dst <&1 - RESULT=$? - if [ $RESULT = 0 ] ; then - if [ "$CHECK" != "" ] && ! $CHECK $MAPPER/$dst $CHECKARGS; then - echo -e "\n - the check for '$MAPPER/$dst' failed" >&2 - #echo " - removing the crypto device $dst" >&2 - #$CRYPTCMD luksClose $dst - sleep 1 + $CRYPTCMD $PARAMS luksOpen $src $dst <&1 + else + if [ -x /sbin/usplash_write -a -p /dev/.initramfs/usplash_outfifo ]; then + MAXTRIES=3 + while [ $MAXTRIES -gt 0 ]; do + MAXTRIES=$(($MAXTRIES - 1)) + /sbin/usplash_write "INPUTQUIET Password for cryptodisk $dst ($src):" + $CRYPTCMD $PARAMS luksOpen $src $dst < /dev/.initramfs/usplash_outfifo + RC=$? + if [ $RC -eq 0 ]; then + break + fi + done + /sbin/usplash_write "CLEAR" + else + $CRYPTCMD $PARAMS luksOpen $src $dst <&1 + RC=$? fi + fi - else - echo -e "\n - Device '$src' is not a LUKS partition, skipping" >&2 - continue + + fi + + if [ $RC != 0 ]; then + return 1 + fi + + if [ "$CHECK" != "" ] && ! $CHECK $MAPPER/$dst $CHECKARGS; then + echo "the check for '$MAPPER/$dst' failed" >&2 + echo "removing the crypto device $dst" >&2 + $CRYPTCMD luksClose $dst + return 1 fi + + return 0 } do_noluks () { if [ "$PRECHECK" = "" ]; then - PRECHECK="/lib/cryptsetup/checks/un_vol_id" + PRECHECK="/lib/cryptsetup/checks/un_vol_id" + fi + + if pre_out=$($PRECHECK $src); then + run=1 + elif test "x$MAKESWAP" = "xyes" && /lib/cryptsetup/checks/vol_id $src swap>/dev/null; then + run=1 + else + run=0 + echo "$pre_out" >&2 + echo "the precheck for '$src' failed, skipping" >&2 + return 1 fi - if $PRECHECK $src; then + + if test "x$KEYSCRIPT" != "x" ; then + PARAMS="$PARAMS --key-file=-" + $KEYSCRIPT $key <&1 | $CRYPTCMD $PARAMS create $dst $src + else if test "x$INTERACTIVE" != "xyes" ; then PARAMS="$PARAMS --key-file=$key" fi $CRYPTCMD $PARAMS create $dst $src <&1 - RESULT=$? - if [ $RESULT = 0 ] ; then - if [ "$CHECK" != "" ] && ! $CHECK $MAPPER/$dst $CHECKARGS; then - echo -e "\n - the check for '$MAPPER/$dst' failed - maybe the password is wrong" >&2 - echo " - removing the crypto device $dst" >&2 - $CRYPTCMD remove $dst - sleep 1 - fi - fi - else - echo -e "\n - the precheck for '$src' failed, skipping" >&2 - continue fi + + if [ $? != 0 ] ; then + return 1 + fi + + + if [ "$CHECK" != "" ] && ! $CHECK $MAPPER/$dst $CHECKARGS; then + echo "the check for '$MAPPER/$dst' failed - maybe the password is wrong" >&2 + echo "removing the crypto device $dst" >&2 + $CRYPTCMD remove $dst + return 1 + fi + + return 0 } mount_fs () { for point in $MOUNT; do - mount $MOUNT 2>/dev/null 1>&2 MOUNT_YES="yes" + mount $point 2>/dev/null 1>&2 || MOUNT_YES="no" done } @@ -348,11 +369,13 @@ do_swap () { if test "x$MAKESWAP" = "xyes" && test -b $MAPPER/$dst; then - if $SWCHECK $MAPPER/$dst $SWCHECKARGS; then + if swap_out=$(/lib/cryptsetup/checks/un_vol_id $MAPPER/$dst) || \ + /lib/cryptsetup/checks/vol_id $MAPPER/$dst swap>/dev/null; then mkswap $MAPPER/$dst 2>/dev/null >/dev/null else - echo -e "\n - the check for '$MAPPER/$dst' failed. $MAPPER/$dst contains data." >&2 - echo " - removing the crypto device $dst" >&2 + echo "$swap_out" >&2 + echo "the check for '$MAPPER/$dst' failed. $MAPPER/$dst contains data." >&2 + echo "removing the crypto device $dst" >&2 do_close fi fi @@ -367,14 +390,8 @@ fi } -clean_keys () { - if [ "$deckey" -a -f "$deckey" ]; then - rm -f $deckey && deckey="" - fi -} - do_close () { - if echo $opt | grep -q "luks"; then + if echo $opts | grep -q "luks"; then $CRYPTCMD luksClose $dst else $CRYPTCMD remove $dst @@ -382,49 +399,63 @@ } do_start () { - modprobe -Qb dm-crypt - + modprobe -q dm-crypt || true $DEVMAPCMD mknodes log_action_begin_msg "Starting $INITSTATE crypto disks" mount_fs - egrep -v "^[[:space:]]*(#|$)" $TABFILE | while read dst src key opt; do - if ! test -r "$src" ; then + egrep -v "^[[:space:]]*(#|$)" $TABFILE | while read dst src key opts; do + + # Make sure that all fields are present + if [ "x$dst" = "x" ]; then + continue + elif [ -z "$src" ] || [ -z "$key" ] || [ -z "$opts" ]; then + log_progress_msg "$dst(skipped, missing parameters)" + continue + fi + + # Make sure source device exists + if [ ! -r "$src" ]; then if [ "x$LOUD" = "xyes" ]; then - echo -e "\n - Device '$src' does not exist, skipping" >&2 + log_progress_msg "$dst(skipped, device $src does not exist)" fi continue fi - if test -b $MAPPER/$dst; then + # Make sure that target device doesn't exist + if [ -b $MAPPER/$dst ]; then log_progress_msg "$dst(running)" - else - log_progress_msg "$dst(starting)" + continue + fi - parse_opts - check_key - lo_setup + # All checks passed, do the real setup + log_progress_msg "$dst(starting)" - if test "x$USELUKS" = "xyes" ; then - do_luks - else - do_noluks - fi + parse_opts "$opts" || continue + check_key || continue + lo_setup || continue + + if test "x$USELUKS" = "xyes" ; then + do_luks + else + do_noluks + fi + + if [ $? -ne 0 ]; then + log_progress_msg "$dst(failed)" + else do_swap do_tmp - - clean_keys fi done umount_fs - echo -n " " - log_action_end_msg $? + log_action_end_msg 0 } do_stop () { $DEVMAPCMD mknodes log_action_begin_msg "Stopping $INITSTATE crypto disks" - egrep -v "^[[:space:]]*(#|$)" $TABFILE | while read dst src key opt; do + egrep -v "^[[:space:]]*(#|$)" $TABFILE | while read dst src key opts; do if test -b $MAPPER/$dst; then if $DEVMAPCMD info $dst | grep -q '^Open count: *0$'; then dev=`$DEVMAPCMD table $dst | sed 's/^.* \([0-9]*:[0-9]*\) .*/\1/'` @@ -446,7 +477,15 @@ fi done - echo -n " " - log_action_end_msg $? + log_action_end_msg 0 } +device_msg () { + local dst msg + dst="$1" + msg="$2" + + if [ "$VERBOSE" != "no" ]; then + log_action_cont_msg "$dst ($msg)" + fi +}