On Wed, Sep 07, 2011 at 03:59:16PM +0100, Colin Watson wrote:
> Here's a first pass at this.  What do people think?

I meant to send my previous version to the first of the merged bug set,
#451535.  I'll send further mails only there rather than to #529343 as
well.

> The one thing I don't think I've got right yet is writing out
> /etc/crypttab at the end of installation.  This needs a bit more work to
> write out the correct files in the partman device directory without
> causing partman to reinitialise the encrypted volume.

Well.  Yes.  That turned out to be the second 90% of the work!  After
trying a few alternatives, I ended up with a new 'crypto_keep' method
and then tried to let init.d/crypto do as much of the work as possible,
while still being careful to avoid reinitialising the contents of
encrypted volumes.

In the process, I also decided that it was better to always have the
Activate option present, without trying to detect existing volumes
first.  That way, we can actively warn people that this method only
works with LUKS where we have a useful encrypted volume header and that
they should back up their data before attempting an installation, rather
than having them get confused into destroying their data as before.

I'm fairly happy with this now, and am inclined to commit it if there
are no objections.  The one problem I've found is that the check for an
unencrypted /boot doesn't work properly when activating existing
LVM-on-crypto volumes, but I think that's actually a pre-existing bug so
I'm not going to let that block this change.

  * Add an "Activate existing encrypted volumes" option to the
    partman-crypto main menu.  If selected, this searches for existing
    volumes, and for each one prompts for its passphrase and attempts to
    open it; it then returns directly to the partitioning menu (closes:
    #451535, LP: #420080).

=== modified file 'check.d/crypto_check_mountpoints'
--- check.d/crypto_check_mountpoints    2008-03-14 19:25:59 +0000
+++ check.d/crypto_check_mountpoints    2011-09-08 19:20:22 +0000
@@ -43,7 +43,7 @@ for dev in $DEVICES/*; do
                [ -f $realdevdir/method ] || continue
                method=$(cat $realdevdir/method)
                type=$(cat $realdevdir/crypto_type)
-               [ $method = crypto ] || continue
+               [ $method = crypto ] || [ $method = crypto_keep ] || continue
 
                # Check 1 - Is cryptoroot possible?
                if [ "$mnt" = / ]; then

=== modified file 'choose_partition/crypto/do_option'
--- choose_partition/crypto/do_option   2009-11-10 14:20:25 +0000
+++ choose_partition/crypto/do_option   2011-09-09 11:30:35 +0000
@@ -12,6 +12,118 @@
 
 . /lib/partman/lib/crypto-base.sh
 
+get_passphrase () {
+       db_set partman-crypto/activate/passphrase-existing ""
+       db_fset partman-crypto/activate/passphrase-existing seen false
+       db_subst partman-crypto/activate/passphrase-existing DEVICE "$1"
+       db_input critical partman-crypto/activate/passphrase-existing
+
+       db_go || return 1
+
+       db_get partman-crypto/activate/passphrase-existing || RET=''
+       echo -n "$RET"
+}
+
+do_cryptsetup () {
+       local dev num id size path
+       local dump cipher keysize ivalgorithm keytype keyhash
+       local cryptdev pass
+
+       dev=$1
+       num=$2
+       id=$3
+       size=$4
+       path=$5
+
+       dump="$(cryptsetup luksDump "$path")"
+       cipher="$(echo "$dump" | sed -n '/^Cipher name:/s/.*[[:space:]]//p')"
+       if [ "$cipher" ]; then
+               crypto_load_udebs "cdebconf-$DEBIAN_FRONTEND-entropy" \
+                                 partman-crypto-dm
+               crypto_check_required_tools dm-crypt
+               crypto_load_modules dm-crypt "$cipher"
+       fi
+       keysize="$(echo "$dump" | sed -n '/^MK bits:/s/.*[[:space:]]//p')"
+       ivalgorithm="$(echo "$dump" | sed -n '/^Cipher 
mode:/s/.*[[:space:]]//p')"
+       keytype=passphrase
+       keyhash="$(echo "$dump" | sed -n '/^Hash spec:/s/.*[[:space:]]//p')"
+
+       cryptdev="${path##*/}_crypt"
+       if ! cryptsetup status "$cryptdev" >/dev/null 2>&1; then
+               while :; do
+                       pass="$(get_passphrase "$path")" || return 1
+                       if [ -z "$pass" ]; then
+                               return 1
+                       fi
+                       echo -n "$pass" | log-output -t partman-crypto \
+                               cryptsetup -d - luksOpen "$path" "$cryptdev" \
+                               && break
+               done
+
+               cryptdev="/dev/mapper/$cryptdev"
+               echo dm-crypt > $id/crypto_type
+               echo "$keysize" > $id/keysize
+               echo "$ivalgorithm" > $id/ivalgorithm
+               echo "$keytype" > $id/keytype
+               echo "$keyhash" > $id/keyhash
+               echo cipher > $id/cipher
+               echo crypto_keep > $id/method
+               echo "$cryptdev" > $id/crypt_active
+
+               db_subst partman-crypto/text/in_use DEV "${cryptdev##*/}"
+               db_metaget partman-crypto/text/in_use description
+               partman_lock_unit "$(mapdevfs "$path")" "$RET"
+       fi
+}
+
+do_activate () {
+       local found_luks dev partitions num id size type fs path name part
+
+       found_luks=0
+       for dev in $DEVICES/*; do
+               [ -d "$dev" ] || continue
+               cd "$dev"
+
+               partitions=
+               open_dialog PARTITIONS
+               while { read_line num id size type fs path name; [ "$id" ]; }; 
do
+                       [ "$fs" != free ] || continue
+                       partitions="$partitions $id,$path"
+               done
+               close_dialog
+
+               for part in $partitions; do
+                       id="${part%%,*}"
+                       path="${part#*,}"
+
+                       if cryptsetup isLuks "$path" 2>/dev/null; then
+                               found_luks=1
+                               do_cryptsetup "$dev" "$num" "$id" "$size" \
+                                       "$path" || continue
+                       fi
+               done
+       done
+
+       if [ "$found_luks" = 0 ]; then
+               db_input critical partman-crypto/activate/no_luks
+               db_go || true
+               return
+       fi
+
+       # Encrypted devices as configured by d-i usually contain LVM PVs
+       export LVM_SUPPRESS_FD_WARNINGS=1
+       log-output -t partman-crypto pvscan
+       log-output -t partman-crypto vgscan
+       log-output -t partman-crypto vgchange -a y
+
+       # Tell partman to detect filesystems again.
+       rm -f /var/lib/partman/filesystems_detected
+
+       stop_parted_server
+       restart_partman
+       exit 0
+}
+
 do_create () {
        local parts line pv output vg pathmap
        parts=""
@@ -93,6 +231,7 @@ while :; do
        db_go || exit 10
        db_get partman-crypto/mainmenu
        case $RET in
+           activate)   do_activate ;; # exits if any volumes were activated
            create)     do_create ;;
            finish)     break ;;
            *)

=== modified file 'debian/control'
--- debian/control      2011-05-03 16:05:09 +0000
+++ debian/control      2011-09-09 12:06:37 +0000
@@ -12,7 +12,7 @@ Vcs-Bzr: http://bazaar.launchpad.net/~ub
 Package: partman-crypto
 XC-Package-Type: udeb
 Architecture: any
-Depends: partman-base (>= 134), cdebconf-udeb (>= 0.133), di-utils (>= 1.68), 
${shlibs:Depends}, ${misc:Depends}
+Depends: partman-base (>= 134), partman-lvm (>= 62), cdebconf-udeb (>= 0.133), 
di-utils (>= 1.68), ${shlibs:Depends}, ${misc:Depends}
 Description: Add to partman support for block device encryption
 
 Package: partman-crypto-dm

=== modified file 'debian/partman-crypto.templates'
--- debian/partman-crypto.templates     2009-12-05 22:29:36 +0000
+++ debian/partman-crypto.templates     2011-09-08 11:16:40 +0000
@@ -430,12 +430,12 @@ _Description: Proceed to install crypto
 
 Template: partman-crypto/mainmenu
 Type: select
-Choices-C: create, finish
+Choices-C: activate, create, finish
 # Note to translators : Please keep your translations of the choices
 # below a 65 columns limit (which means 65 characters
 # in single-byte languages)
 # :sl3:
-__Choices: Create encrypted volumes, Finish
+__Choices: Activate existing encrypted volumes, Create encrypted volumes, 
Finish
 # :sl3:
 _Description: Encryption configuration actions
  This menu allows you to configure encrypted volumes.
@@ -454,3 +454,20 @@ Type: error
 # :sl3:
 _Description: No devices selected
  No devices were selected for encryption.
+
+Template: partman-crypto/activate/no_luks
+Type: error
+# :sl3:
+_Description: No LUKS devices found
+ This partitioning program can only activate existing encrypted volumes that
+ use the LUKS format (dm-crypt with a passphrase). No such volumes were
+ found. If you have encrypted volumes using other formats, you may need to
+ back up your data before continuing with installation.
+
+Template: partman-crypto/activate/passphrase-existing
+Type: password
+# :sl3:
+_Description: Passphrase for ${DEVICE}:
+ Please enter the passphrase for the encrypted volume ${DEVICE}.
+ .
+ If you don't enter anything, the volume will not be activated.

=== modified file 'finish.d/crypto_aptinstall'
--- finish.d/crypto_aptinstall  2008-03-20 21:06:33 +0000
+++ finish.d/crypto_aptinstall  2011-09-07 22:17:00 +0000
@@ -39,7 +39,7 @@ for dev in $DEVICES/*; do
                [ -f $id/crypto_type ] || continue
 
                method=$(cat $id/method)
-               [ $method = crypto ] || continue
+               [ $method = crypto ] || [ $method = crypto_keep ] || continue
 
                type=$(cat $id/crypto_type)
                case $type in

=== modified file 'init.d/crypto'
--- init.d/crypto       2010-05-27 09:44:55 +0000
+++ init.d/crypto       2011-09-09 12:36:17 +0000
@@ -4,6 +4,17 @@
 # setup in choose_partition/crypto/do_option.
 
 . /lib/partman/lib/base.sh
+. /lib/partman/lib/lvm-base.sh
+
+# Avoid warnings from lvm2 tools about open file descriptors
+export LVM_SUPPRESS_FD_WARNINGS=1
+
+if [ -x /sbin/vgdisplay ]; then
+       vgroups=$(/sbin/vgdisplay 2>/dev/null | grep '^[ ]*VG Name' | \
+               sed -e 's/.*[[:space:]]\(.*\)$/\1/' | sort)
+else
+       vgroups=''
+fi
 
 dev_to_devdir () {
        echo $DEVICES/$(echo $1 | tr / =)
@@ -72,7 +83,7 @@ create_partition () {
 }
 
 create_cryptdisk () {
-       local dev id num size path cryptdev cipher
+       local dev id num size path cryptdev cipher file vg vgs
        dev=$1
        id=$2
        num=$3
@@ -81,6 +92,7 @@ create_cryptdisk () {
 
        cipher=$(cat $id/cipher)
        keytype=$(cat $id/keytype)
+       method=$(cat $id/method)
 
        templ="partman-crypto/text/cryptdev_description"
        db_subst $templ CIPHER $cipher
@@ -128,17 +140,47 @@ create_cryptdisk () {
        case $filesystem in
                linux-swap)
                        echo swap > $cryptpart/method
-                       >$cryptpart/format
+                       if [ "$method" = crypto ]; then
+                               >$cryptpart/format
+                       else
+                               rm -f $cryptpart/format
+                       fi
                        ;;
 
                $default_fs)
-                       echo format > $cryptpart/method
-                       >$cryptpart/format
-                       >$cryptpart/use_filesystem
-                       echo $filesystem > $cryptpart/filesystem
+                       if [ "$method" = crypto ]; then
+                               echo format > $cryptpart/method
+                               >$cryptpart/format
+                               >$cryptpart/use_filesystem
+                               echo $filesystem > $cryptpart/filesystem
+                       else
+                               echo keep > $cryptpart/method
+                               rm -f $cryptpart/format
+                       fi
                        ;;
        esac
 
+       # To avoid ordering problems between init.d/crypto and init.d/lvm,
+       # we need to duplicate a bit of the latter here, in case an existing
+       # crypto device contains an LVM PV.
+       if [ "$method" = crypto_keep ]; then
+               if pvdisplay "$cryptdev" >/dev/null 2>&1; then
+                       for file in acting_filesystem filesystem format \
+                                   formatable use_filesystem; do
+                               rm -f $cryptpart/$file
+                       done
+                       echo lvm > $cryptpart/method
+                       if [ ! -e $cryptpart/locked ]; then
+                               vg="$(pv_get_vg "$cryptdev")"
+                               for vgs in $vgroups; do
+                                       if [ "$vg" = "$vgs" ]; then
+                                               vg_lock_pvs "$vg" "$cryptdev"
+                                       fi
+                               done
+                       fi
+               fi
+       fi
+
        update_partition $cryptdir $cryptid
 
        echo $path:$num:$dev/$id > $cryptdir/crypt_realdev
@@ -174,7 +216,7 @@ for dev in /var/lib/partman/devices/*; d
                [ -f $id/crypt_active ] || continue
 
                method=$(cat $id/method)
-               [ $method = crypto ] || continue
+               [ $method = crypto ] || [ $method = crypto_keep ] || continue
 
                if ! create_cryptdisk $dev $id $num $size $path; then
                        db_fset partman-crypto/init_failed seen false

=== modified file 'lib/crypto-base.sh'
--- lib/crypto-base.sh  2011-08-26 12:20:00 +0000
+++ lib/crypto-base.sh  2011-09-07 22:27:14 +0000
@@ -82,7 +82,7 @@ crypto_prepare () {
        if [ "$method" = swap ]; then
                disable_swap "$dev" "$id"
        fi
-       if [ "$method" != crypto ]; then
+       if [ "$method" != crypto ] && [ "$method" != crypto_keep ]; then
                crypto_prepare_method "$id" dm-crypt || return 1
                rm -f "$id/use_filesystem"
                rm -f "$id/format"
@@ -820,7 +820,8 @@ crypto_check_setup() {
                        [ -f $id/crypto_type ] || continue
 
                        method=$(cat $id/method)
-                       if [ $method != crypto ]; then
+                       if [ $method != crypto ] && \
+                          [ $method != crypto_keep ]; then
                                continue
                        fi
                        type=$(cat $id/crypto_type)

=== modified file 'update.d/crypto_visuals'
--- update.d/crypto_visuals     2007-12-05 20:18:24 +0000
+++ update.d/crypto_visuals     2011-09-07 22:16:23 +0000
@@ -37,8 +37,9 @@ cryptdev_shortname ()
        esac
 }
 
-if [ $method = crypto ]; then
-       db_metaget partman/method_short/$method description || RET=''
+case $method in
+    crypto|crypto_keep)
+       db_metaget partman/method_short/crypto description || RET=''
        echo ${RET:-crypto} >$id/visual_filesystem
 
        if [ -f $id/crypt_active ]; then
@@ -52,5 +53,6 @@ if [ $method = crypto ]; then
 
        # open_dialog CHANGE_FILE_SYSTEM $id linux-swap
        # close_dialog
-fi
+       ;;
+esac
 
-- 
Colin Watson                                       [[email protected]]



-- 
To UNSUBSCRIBE, email to [email protected]
with a subject of "unsubscribe". Trouble? Contact [email protected]
Archive: 
http://lists.debian.org/[email protected]

Reply via email to