CRYPTCMD=/sbin/cryptsetup DEVMAPCMD=/sbin/dmsetup LOSETUP=/sbin/losetup TABFILE=/etc/crypttab MAPPER=/dev/mapper MOUNT="${CRYPTDISKS_MOUNT}" test -x $CRYPTCMD || exit 0 test -x $DEVMAPCMD || exit 0 test -f $TABFILE || exit 0 parse_opts () { local 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 while test "x$opts" != "x" ; do ARG=`echo $opts | sed "s/,.*//"` opts=${opts##$ARG} opts=${opts##,} PARAM=`echo $ARG | sed "s/=.*//"` case "$ARG" in *=*) PARAM=`echo $ARG | sed "s/=.*//"` VALUE=${ARG##$PARAM=} ;; *) PARAM=$ARG VALUE="" ;; esac case "$PARAM" in readonly) PARAMS="$PARAMS -r" ;; cipher) PARAMS="$PARAMS -c $VALUE" if test "x$VALUE" = "x" ; then echo "no value for cipher option, skipping" >&2 return 1 fi ;; size) PARAMS="$PARAMS -s $VALUE" if test "x$VALUE" = "x" ; then echo "no value for size option, skipping" >&2 return 1 fi ;; hash) PARAMS="$PARAMS -h $VALUE" if test "x$VALUE" = "x" ; then echo "no value for hash option, skipping" >&2 return 1 fi ;; verify) PARAMS="$PARAMS -y" ;; check) if test "x$VALUE" = "x" ; then CHECK="${CRYPTDISKS_CHECK}" else CHECK="$VALUE" fi if [ "$CHECK" -a -x /lib/cryptsetup/checks/"$CHECK" ]; then CHECK="/lib/cryptsetup/checks/$CHECK" #else # CHECK="" fi ;; checkargs) if test "x$VALUE" != "x"; then CHECKARGS="$VALUE" fi ;; precheck) if test "x$VALUE" = "x" ; then PRECHECK="${CRYPTDISKS_PRECHECK}" else PRECHECK="$VALUE" fi if [ "$PRECHECK" -a -x /lib/cryptsetup/checks/"$PRECHECK" ]; then PRECHECK="/lib/cryptsetup/checks/$PRECHECK" else PRECHECK="" fi ;; tries) if test "x$VALUE" != "x" ; then TRIES="$VALUE" fi case "$TRIES" in [0-9]*) ;; *) echo "option TRIES is wrongly set to $TRIES - forced to '3' " >&2 TRIES="3" ;; esac PARAMS="$PARAMS --tries=$TRIES" ;; timeout) if test "x$VALUE" = "x" ; then TIMEOUT="${CRYPTDISKS_TIMEOUT}" else TIMEOUT="$VALUE" fi case "$TIMEOUT" in [0-9]*) ;; *) echo "option TIMEOUT is wrongly set to $TIMEOUT - forced to '0' " >&2 TIMEOUT="0" ;; esac 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 ;; ssl) 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) 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 return 0 } lo_setup () { local LOOP_ID="" # Set up loopback devices if [ ! -f "$src" ]; then return 0 fi if [ ! -d "/sys/block/loop0" ]; then modprobe loop || return 1 fi 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 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 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 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 fi if [ $? != 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" 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 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 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_YES="yes" echo "STICK!" read mount $point 2>/dev/null 1>&2 || MOUNT_YES="no" done } umount_fs () { if [ "x$MOUNT_YES" = "xyes" ]; then for point in $MOUNT; do umount $point done fi } do_swap () { if test "x$MAKESWAP" = "xyes" && test -b $MAPPER/$dst; 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 "$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 } do_tmp () { if test "x$MAKETMP" = "xyes" && test -b $MAPPER/$dst; then mke2fs $MAPPER/$dst >/dev/null mount -t ext2 $MAPPER/$dst /tmp chmod 1777 /tmp umount /tmp fi } do_close () { if echo $opts | grep -q "luks"; then $CRYPTCMD luksClose $dst else $CRYPTCMD remove $dst fi } do_start () { 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 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 log_progress_msg "$dst(skipped, device $src does not exist)" fi continue fi # Make sure that target device doesn't exist if [ -b $MAPPER/$dst ]; then log_progress_msg "$dst(running)" continue fi # All checks passed, do the real setup log_progress_msg "$dst(starting)" 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 fi done umount_fs 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 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/'` major=`echo $dev | sed 's/:.*//'` minor=`echo $dev | sed 's/.*://'` log_progress_msg "$dst(stopping)" do_close # Detach loopback device, if attached if test -f $src -a $major -eq 7; then $LOSETUP -d /dev/loop$minor fi else log_progress_msg "$dst(busy)" fi else log_progress_msg "$dst(stopped)" fi done 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 }