Hello, if anyone besides me is using the yaird loop-AES support patches, here's a small update to patch 1106 with two minor fixes.
- 1106_add_loopback_and_loopaes_with_loopaestab_support_v5a.patch * In FsEntry.pm, add a check to ensure the "loop" option within an fstab entry actually specifies a loop device. (We cannot support randomly allocated loop devices with yaird.) * Fix the loadkeys template to work with recent gzip package versions (>= 1.3.12-1). See #435231 for details. Besides that, yaird loop-AES support still works without a hitch using the official Debian kernel images (extended by an appropriate loop-aes-modules-* package, of course). Regards, Peter
diff -urN yaird-0.0.12.orig/perl/ActiveBlockDev.pm yaird-0.0.12/perl/ActiveBlockDev.pm --- yaird-0.0.12.orig/perl/ActiveBlockDev.pm 2006-10-26 15:41:37.000000000 +0200 +++ yaird-0.0.12/perl/ActiveBlockDev.pm 2006-10-26 15:45:01.000000000 +0200 @@ -173,6 +173,10 @@ Base::assert ($name =~ /^md\d+$/); $self->{yspecial} = "/dev/$name"; } + elsif ($creator eq "losetup") { + Base::assert ($name =~ /^loop\d+$/); + $self->{yspecial} = "/dev/$name"; + } elsif ($creator eq "devmapper") { Base::assert ($name =~ /^dm-\d+$/); my $paths = BlockSpecialFileTab::pathsByDevno ($devno); diff -urN yaird-0.0.12.orig/perl/Conf.pm.in yaird-0.0.12/perl/Conf.pm.in --- yaird-0.0.12.orig/perl/Conf.pm.in 2006-10-26 15:41:37.000000000 +0200 +++ yaird-0.0.12/perl/Conf.pm.in 2006-10-26 15:45:01.000000000 +0200 @@ -61,6 +61,7 @@ procFs => sub { "/proc"; }, dev => sub { "/dev"; }, fstab => sub { "/etc/fstab"; }, + loopaestab => sub { "/etc/loopaestab"; }, crypttab => sub { "/etc/crypttab"; }, hotplug => sub { "/etc/hotplug"; }, appVersion => sub { "@VERSION@"; }, diff -urN yaird-0.0.12.orig/perl/FsEntry.pm yaird-0.0.12/perl/FsEntry.pm --- yaird-0.0.12.orig/perl/FsEntry.pm 2006-10-26 15:41:37.000000000 +0200 +++ yaird-0.0.12/perl/FsEntry.pm 2006-10-26 15:53:47.000000000 +0200 @@ -83,8 +83,12 @@ my $msg = undef; if ($dev =~ /^\//) { - if ($self->opts->exists('loop')) { - $msg = "loopback mount for '$dev' not supported ($origin)"; + if ($self->opts->exists ('loop') && $self->type eq 'swap') { + $msg = "loop option for swap device '$dev' not supported ($origin)"; return (undef, $msg); } + if ($self->opts->exists ('loop') && ! defined ($self->opts->get ('loop'))) { + $msg = "loop option without loop device not supported ($origin)"; + return (undef, $msg); + } if (-f $dev && $self->type eq "swap") { @@ -92,6 +96,10 @@ return (undef, $msg); } + if ($self->opts->exists ('loop')) { + $dev = $self->opts->get ('loop'); + } + if (! -e $dev) { $msg = "'$dev' not found ($origin)"; return (undef, $msg); diff -urN yaird-0.0.12.orig/perl/FsOpts.pm yaird-0.0.12/perl/FsOpts.pm --- yaird-0.0.12.orig/perl/FsOpts.pm 2006-10-26 15:41:37.000000000 +0200 +++ yaird-0.0.12/perl/FsOpts.pm 2006-10-26 15:45:01.000000000 +0200 @@ -43,6 +43,19 @@ next if $key eq 'user'; next if $key eq 'users'; next if $key eq 'defaults'; + + # loop and loop-AES attributes + next if $key eq 'loop'; + next if $key eq 'offset'; + next if $key eq 'sizelimit'; + next if $key eq 'encryption'; + next if $key eq 'pseed'; + next if $key eq 'phash'; + next if $key eq 'loinit'; + next if $key eq 'gpgkey'; + next if $key eq 'gpghome'; + next if $key eq 'itercountk'; + my $val = $opts->{$key}; if (defined ($val)) { push @cmdLine, "$key=$val"; diff -urN yaird-0.0.12.orig/perl/KConfig.pm yaird-0.0.12/perl/KConfig.pm --- yaird-0.0.12.orig/perl/KConfig.pm 2006-10-26 15:44:48.000000000 +0200 +++ yaird-0.0.12/perl/KConfig.pm 2006-10-26 15:45:01.000000000 +0200 @@ -208,6 +208,9 @@ # Compaq Smart Array controllers 'cpqarray' => [ 'BLK_CPQ_DA' ], 'cciss' => [ 'BLK_CPQ_CISS_DA' ], + + # loopback + 'loop' => [ 'BLK_DEV_LOOP' ], }; diff -urN yaird-0.0.12.orig/perl/LoopAesEntry.pm yaird-0.0.12/perl/LoopAesEntry.pm --- yaird-0.0.12.orig/perl/LoopAesEntry.pm 1970-01-01 01:00:00.000000000 +0100 +++ yaird-0.0.12/perl/LoopAesEntry.pm 2006-10-26 15:45:01.000000000 +0200 @@ -0,0 +1,48 @@ +#!perl -w +# +# LoopAesEntry -- encapsulate a single entry in /etc/loopaestab +# Copyright (C) 2006 Peter Colberg +# +# Based on CryptEntry -- encapsulate a single entry in /etc/crypttab +# Copyright (C) 2005 Erik van Konijnenburg +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +use strict; +use warnings; +package LoopAesEntry; +use base 'Obj'; + +sub fill { + my $self = shift; + $self->SUPER::fill(); + $self->takeArgs ('target', 'source', 'opts', 'origin'); +} + +sub target { return $_[0]->{target}; } +sub source { return $_[0]->{source}; } +sub opts { return $_[0]->{opts}; } +sub origin { return $_[0]->{origin}; } + +sub string { + my $self = shift; + my $target = $self->target(); + my $source = $self->source(); + my $opts = $self->opts()->string(); + return "$target in $source with $opts"; +} + + +1; diff -urN yaird-0.0.12.orig/perl/LoopAesTab.pm yaird-0.0.12/perl/LoopAesTab.pm --- yaird-0.0.12.orig/perl/LoopAesTab.pm 1970-01-01 01:00:00.000000000 +0100 +++ yaird-0.0.12/perl/LoopAesTab.pm 2006-10-26 15:45:01.000000000 +0200 @@ -0,0 +1,120 @@ +#!perl -w +# +# LoopAesTab -- encapsulate /etc/loopaestab. +# Copyright (C) 2006 Peter Colberg +# +# Based on CryptTab -- encapsulate /etc/crypttab. +# Copyright (C) 2005 Erik van Konijnenburg +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +use strict; +use warnings; +use Base; +use Conf; +use LoopAesEntry; +package LoopAesTab; + + +my $loopAesTab = undef; + + +sub init () { + if (defined ($loopAesTab)) { + return; + } + $loopAesTab = []; + my $name = Conf::get('loopaestab'); + if (! -e $name) { + # + # It's OK if there's no /etc/loopaestab, but if it + # exists, it had better be readable. + # + return; + } + if (! open (IN, "<", "$name")) { + Base::fatal ("can't read $name"); + } + my $lineNo = 0; + while (defined (my $line = <IN>)) { + $lineNo++; + chomp $line; + + $line =~ s/^\s*//; + next if $line =~ /^#/; # comment line + next if $line eq ""; + + my @fields = split (/\s+/, $line); + if (@fields < 2) { + Base::fatal ("no source device in $name:$lineNo"); + } + my $target = shift @fields; + my $source = shift @fields; + my $optString = (shift @fields or ''); + my $opts = Opts->new (string => $optString); + + my $descr = LoopAesEntry->new( + target => $target, + source => $source, + opts => $opts, + origin => "$name:$lineNo", + ); + push @{$loopAesTab}, $descr; + } + if (! close (IN)) { + Base::fatal ("could not read $name"); + } +} + +sub all () { + init; + return $loopAesTab; +} + +sub findByTarget ($) { + my ($target) = @_; + my $result; + my $devno = Base::devno ($target); + if (! defined ($devno)) { + Base::fatal ("cannot find device number for: $target"); + } + return findByDevno ($devno); +} + +sub findByDevno ($) { + my ($devno) = @_; + my $result = undef; + + for my $entry (@{LoopAesTab::all()}) { + my $b2 = $entry->target; + my $n2 = Base::devno ($b2); + if (! defined ($n2)) { + next; + } + + if ($n2 eq $devno) { + if (defined ($result)) { + my $o1 = $entry->origin; + my $o2 = $result->origin; + Base::fatal ("duplicate device '$b2' in $o1, $o2"); + } + $result = $entry; + } + } + return $result; +} + + +1; diff -urN yaird-0.0.12.orig/perl/LoopAesVersion.pm yaird-0.0.12/perl/LoopAesVersion.pm --- yaird-0.0.12.orig/perl/LoopAesVersion.pm 1970-01-01 01:00:00.000000000 +0100 +++ yaird-0.0.12/perl/LoopAesVersion.pm 2006-10-26 15:45:01.000000000 +0200 @@ -0,0 +1,104 @@ +#!perl -w +# +# LoopAesVersion -- utility functions to probe for loop-AES support +# Copyright (C) 2006 Peter Colberg +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +use strict; +use warnings; +use Base; +package LoopAesVersion; + +my $hasLoopAesModule = undef; +my $hasLoopAesSetup = undef; + +# +# Probe loop-AES patched loop module +# +sub probeLoopAesModule ($) { + my ($path) = @_; + my @strings = ( + 'loop_compute_sector_iv', + 'loop_compute_md5_iv_v3', + ); + $hasLoopAesModule = grepBinary ($path, @strings); +} + +# +# Probe loop-AES patched losetup program +# +sub probeLoopAesSetup ($) { + my ($path) = @_; + my @strings = ( + 'multi-key-v2', + 'multi-key-v3', + ); + $hasLoopAesSetup = grepBinary ($path, @strings); +} + +# +# Check if userspace and kernel loopback versions match +# +sub matchingVersions () { + if (KConfig::isBuiltIn ('loop')) { + # You are on your own here... + return 1; + } + if (! defined ($hasLoopAesModule)) { + Base::fatal ("unknown loop module version"); + } + if (! defined ($hasLoopAesSetup)) { + Base::fatal ("unknown losetup version"); + } + return ($hasLoopAesModule == $hasLoopAesSetup); +} + +# +# Check if binary file matches given strings +# +sub grepBinary ($@) { + my ($path, @strings) = @_; + my ($len, $buf, $prevbuf); + my %unseen = map { $_, 1 } @strings; + + $len = 1024; + for my $s (keys (%unseen)) { + while (length ($s) > $len) { + $len = ($len << 1); + } + } + if (! open (IN, "<", "$path")) { + return undef; + } + binmode (IN); + $prevbuf = ''; + while (read (IN, $buf, $len)) { + $_ = $prevbuf . $buf; + for my $s (keys (%unseen)) { + if (index ($_, $s) >= $[) { + delete $unseen{$s}; + } + } + last if (! keys (%unseen)); + $prevbuf = $buf; + } + close (IN); + + return (! keys (%unseen)); +} + + +1; diff -urN yaird-0.0.12.orig/perl/LoopDev.pm yaird-0.0.12/perl/LoopDev.pm --- yaird-0.0.12.orig/perl/LoopDev.pm 1970-01-01 01:00:00.000000000 +0100 +++ yaird-0.0.12/perl/LoopDev.pm 2006-10-26 15:45:01.000000000 +0200 @@ -0,0 +1,49 @@ +#!perl -w +# +# LoopDev -- the probed values for a loopback device, as found by losetup. +# Copyright (C) 2006 Peter Colberg +# +# Based on RaidDev -- the probed values for a raid device, as found by mdadm. +# Copyright (C) 2005 Erik van Konijnenburg +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +use strict; +use warnings; +package LoopDev; +use base 'Obj'; + +sub fill { + my $self = shift; + $self->SUPER::fill(); + $self->takeArgs ('target', 'devno', 'opts', 'source'); +} + +sub target { return $_[0]->{target}; } +sub devno { return $_[0]->{devno}; } +sub opts { return $_[0]->{opts}; } +sub source { return $_[0]->{source}; } + +sub string { + my $self = shift; + my $target = $self->target; + my $devno = $self->devno; + my $opts = $self->opts->string; + my $source = $self->source; + return "$target($devno) on $source" . ($opts ? " with $opts" : ""); +} + + +1; diff -urN yaird-0.0.12.orig/perl/LoopTab.pm yaird-0.0.12/perl/LoopTab.pm --- yaird-0.0.12.orig/perl/LoopTab.pm 1970-01-01 01:00:00.000000000 +0100 +++ yaird-0.0.12/perl/LoopTab.pm 2006-10-26 15:45:01.000000000 +0200 @@ -0,0 +1,178 @@ +#!perl -w +# +# LoopTab -- encapsulate losetup output +# Copyright (C) 2006 Peter Colberg +# +# Based on RaidTab -- encapsulate mdadm output +# Copyright (C) 2005 Erik van Konijnenburg +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# +use strict; +use warnings; +use ActiveBlockDevTab; +use Base; +use BlockSpecialFileTab; +use LoopAesVersion; +use LoopDev; +package LoopTab; + + +my $loopTab = undef; + + +# +# init -- initialise table of all known loopback devices. +# +sub init () { + if (defined ($loopTab)) { + return; + } + + $loopTab = []; + + for my $abd (@{ActiveBlockDevTab::all ()}) { + next if (! ($abd->name =~ /^loop\d+$/)); + my $paths = BlockSpecialFileTab::pathsByDevno ($abd->devno); + next if (! defined ($paths)); + my ($rc, $lines) = Base::runCmd (missingOk => 1, failOk => 1, + cmd => ['/sbin/losetup', $paths->[0]]); + if ($rc && defined ($lines) && @{$lines} == 1) { + processLine ($lines->[0]); + } + } + if (@{$loopTab}) { + LoopAesVersion::probeLoopAesSetup ('/sbin/losetup'); + } +} + +# +# processLine -- parse losetup output for a single loopback device +# +# Both native and loop-AES patched losetup syntax is supported. +# +# Example native syntax: +# /dev/loop0: [0900]:57004 (/dev/md0), offset 1000000 +# +# Example loop-AES syntax: +# /dev/loop1: [000e]:3762 (/dev/vg/swap) offset=1024 sizelimit=20971520 encryption=AES256 multi-key-v3 loinit=123 +# +# Parsing expressions were derived from the function 'show_loop' +# in file 'mount/lomount.c' of the unpatched and loop-AES (v3.1d) +# patched util-linux package (v2.12r). +# +sub processLine ($) { + my ($line) = @_; + + my ($target, $source, @attributes, @opts); + + # common device description + if ($line =~ /^(\S+): \[[[:xdigit:]]+\]:\d+ \((\S+)\)(?:(,? )(.*))?$/) { + $target = $1; + $source = $2; + if (defined ($4)) { + @attributes = split (/$3/, $4); + } + } + else { + Base::fatal ("could not parse losetup output: '$line'"); + } + + for my $attr (@attributes) { + # common attribute + if ($attr =~ /^offset[ =](@?\d+)$/) { + push @opts, "offset=$1"; + } + # loop-AES attribute + elsif ($attr =~ /^sizelimit=(\d+)$/) { + push @opts, "sizelimit=$1"; + } + # non-loop-AES attribute + elsif ($attr =~ /^sizelimit (\d+)$/) { + # info-only attribute + } + # loop-AES attribute + elsif ($attr =~ /^encryption=(\S+)$/) { + push @opts, "encryption=$1"; + } + # non-loop-AES attribute + elsif ($attr =~ /^encryption /) { + Base::fatal ("cryptoloop device ('$target') not supported"); + } + # loop-AES attribute + elsif ($attr =~ /^loinit=(\d+)$/) { + push @opts, "loinit=$1"; + } + # loop-AES attribute + elsif ($attr =~ /^read-only$/) { + Base::fatal ("read-only loopback device ('$target') not supported"); + } + # loop-AES attribute + elsif ($attr =~ /^multi-key-(v[23])$/) { + # + # Note: If a loopback device is in multi-key mode, + # a GPG encryption key is definitely required. + # + push @opts, "multikey=$1"; + } + else { + Base::fatal ("unknown attribute '$attr' in losetup output"); + } + } + my $optString = join (",", @opts); + my $opts = Opts->new (string => $optString); + + my $devno = Base::devno ($target); + if (! defined($devno)) { + Base::fatal ("device '$target' in losetup output: can't find device major/minor number"); + } + + my $descr = LoopDev->new ( + target => $target, + devno => $devno, + opts => $opts, + source => $source, + ); + push @{$loopTab}, $descr; +} + +sub all () { + init; + return $loopTab; +} + +sub findByTarget ($) { + my ($target) = @_; + for my $ld (@{all()}) { + if ($ld->target() eq $target) { + return $ld; + } + } + return undef; +} + +sub findByDevno ($) { + my ($devno) = @_; + for my $ld (@{all()}) { + if ($ld->devno() eq $devno) { + return $ld; + } + } + return undef; +} + + +1; diff -urN yaird-0.0.12.orig/perl/Makefile.am yaird-0.0.12/perl/Makefile.am --- yaird-0.0.12.orig/perl/Makefile.am 2006-10-26 15:41:37.000000000 +0200 +++ yaird-0.0.12/perl/Makefile.am 2006-10-26 15:45:01.000000000 +0200 @@ -71,6 +71,11 @@ LabeledPartition.pm \ LabeledPartitionTab.pm \ LogicalVolume.pm \ + LoopAesEntry.pm \ + LoopAesTab.pm \ + LoopAesVersion.pm \ + LoopDev.pm \ + LoopTab.pm \ LvmTab.pm \ ModProbe.pm \ NetDev.pm \ diff -urN yaird-0.0.12.orig/perl/Makefile.in yaird-0.0.12/perl/Makefile.in --- yaird-0.0.12.orig/perl/Makefile.in 2006-10-26 15:41:37.000000000 +0200 +++ yaird-0.0.12/perl/Makefile.in 2006-10-26 15:45:01.000000000 +0200 @@ -229,6 +229,11 @@ LabeledPartition.pm \ LabeledPartitionTab.pm \ LogicalVolume.pm \ + LoopAesEntry.pm \ + LoopAesTab.pm \ + LoopAesVersion.pm \ + LoopDev.pm \ + LoopTab.pm \ LvmTab.pm \ ModProbe.pm \ NetDev.pm \ diff -urN yaird-0.0.12.orig/perl/ModProbe.pm yaird-0.0.12/perl/ModProbe.pm --- yaird-0.0.12.orig/perl/ModProbe.pm 2006-10-26 15:41:37.000000000 +0200 +++ yaird-0.0.12/perl/ModProbe.pm 2006-10-26 15:45:01.000000000 +0200 @@ -90,6 +90,7 @@ use ActionList; use Blacklist; use KConfig; +use LoopAesVersion; package ModProbe; @@ -147,6 +148,15 @@ Base::fatal ("modprobe shows that module $m needs an external program; this is not supported. The offending line is: install $1"); } elsif ($line =~ /^insmod (\S+)$/) { + if ($m eq 'loop' ) { + # + # There exist two different loop modules both + # named 'loop': a native version and a loop-AES + # patched version. + # + LoopAesVersion::probeLoopAesModule ($1); + } + $actionList->add ("insmod", $1, optionList => ''); } diff -urN yaird-0.0.12.orig/perl/Plan.pm yaird-0.0.12/perl/Plan.pm --- yaird-0.0.12.orig/perl/Plan.pm 2006-10-26 15:44:48.000000000 +0200 +++ yaird-0.0.12/perl/Plan.pm 2006-10-26 16:09:02.000000000 +0200 @@ -33,6 +33,9 @@ use ActionList; use CryptTab; use NetDevTab; +use LoopAesTab; +use LoopTab; +use LoopAesVersion; package Plan; @@ -89,6 +92,7 @@ $ok || ($ok = tryDmCrypt ($actions,$device,[$device,@{$working}])); $ok || ($ok = tryLvm ($actions,$device,[$device,@{$working}])); $ok || ($ok = tryRaid ($actions,$device,[$device,@{$working}])); + $ok || ($ok = tryLoop ($actions,$device,[$device,@{$working}])); $ok || ($ok = tryHardware ($actions,$device,[$device,@{$working}])); if (! $ok) { Base::fatal ("unsupported device required: $name"); @@ -427,6 +431,412 @@ return 1; } + +# +# tryLoop -- To start a loopback device, start the underlying hardware, +# optionally make available a GPG encryption key by mounting (and +# later on unmounting) the respective filesystem at boot time or +# copying it to the image at build time, load the loop module and +# optional encryption modules, and setup the loopback device. +# +sub tryLoop ($$$) { + my ($actions, $device, $working) = @_; + + my $name = $device->name; + if ($name !~ /^loop\d+$/) { + return 0; + } + my $devno = $device->devno; + my ($major, $minor) = ($devno =~ /(\d+):(\d+)/); + + my $loopdev = LoopTab::findByDevno ($devno); + if (! defined ($loopdev)) { + Base::fatal ("can't find Loop info for $name"); + } + + # start the underlying block device + my $subdev = ActiveBlockDevTab::findByPath ($loopdev->source); + if (! defined ($subdev)) { + my $source = $loopdev->source; + Base::fatal ("invalid block device '$source' for $name"); + } + addDevicePlan ($actions, $subdev, $working); + + + # + # In most cases, the losetup status output only provides + # a partial set of the attributes required to setup a + # loop-AES device. For a complete set of attributes, we + # therefore need to parse fstab and loopaestab in addition, + # and all given attribute sets have to be compared and + # merged in a nit-picky fashion. + # + + # complete loopback device config + my %loopOpts; + + # + # Full set of possible attributes for each loop device + # config source, i.e. losetup info, fstab and loopaestab. + # + # For the purpose of comparison, an attribute is either + # marked as case sensitive (e.g. 'gpgkey' => 1) or case + # insensitive (e.g. 'encryption' => 0), or undefined if + # not having a value at all (e.g. 'gpgmount' => undef). + # + my $commonSupportedOpts = { + 'offset' => 0, + 'sizelimit' => 0, + 'encryption' => 0, + 'loinit' => 0, + }; + my $losetupSupportedOpts = { + %{$commonSupportedOpts}, + 'multikey' => 0, + }; + my $fsTabSupportedOpts = { + %{$commonSupportedOpts}, + 'gpgkey' => 1, + 'gpghome' => 1, + 'pseed' => 0, + 'phash' => 0, + 'itercountk' => 0, + }; + my $loopAesTabSupportedOpts = { + %{$fsTabSupportedOpts}, + 'gpgmount' => undef, + }; + + # available loop device config entries + my @conf; + + # + # All attributes shown by losetup describe the actual + # loopback device, so this set of attributes is made + # the highest-priority config source. + # + push @conf, { + supportedOpts => $losetupSupportedOpts, + opts => $loopdev->opts, + origin => 'losetup status', + }; + + # query fstab entry for the loopback device + my $fsTabEntry = FsTab::findByDevno ($loopdev->devno); + # ensure that fstab entry has been found via loop= option + if (defined ($fsTabEntry) && $fsTabEntry->opts->exists ('loop')) { + # + # The forbidden case of a loopback swap device with a + # random encryption key is handled within FsTab, + # so this does not have to be reconsidered here. + # + + # check if underlying block device is set correctly + my $n = Base::devno ($fsTabEntry->dev); + if ((! defined ($n)) || (! ($n eq $subdev->devno))) { + my $origin = $fsTabEntry->origin; + Base::fatal ("invalid source device for $name in $origin"); + } + push @conf, { + supportedOpts => $fsTabSupportedOpts, + opts => $fsTabEntry->opts, + origin => $fsTabEntry->origin, + }; + } + + # query loopaestab entry for the loopback device + my $loopAesTabEntry = LoopAesTab::findByDevno ($loopdev->devno); + if (defined ($loopAesTabEntry)) { + # check if underlying block device is set correctly + my $n = Base::devno ($loopAesTabEntry->source); + if ((! defined ($n)) || (! ($n eq $subdev->devno))) { + my $origin = $loopAesTabEntry->origin; + Base::fatal ("invalid source device for $name in $origin"); + } + push @conf, { + supportedOpts => $loopAesTabSupportedOpts, + opts => $loopAesTabEntry->opts, + origin => $loopAesTabEntry->origin, + }; + } + + # + # For every distinct pair of config entries, all attributes + # supported by both config sources strictly have to match. + # + my @confpairs; + for my $i (0 .. ($#conf - 1)) { + for my $j (($i + 1) .. $#conf) { + push @confpairs, [ $conf[$i], $conf[$j] ]; + } + } + for my $p (@confpairs) { + my (%count, @intersect, @conflicts); + my @suppOpts = map { keys (%{$_->{supportedOpts}}) } @{$p}; + + # determine common set of supported attributes + for my $opt (@suppOpts) { + if (++$count{$opt} == 2) { + push @intersect, $opt; + } + } + + # basically do a case (in)sensitive hash comparison + for my $opt (@intersect) { + my @exists = map { $_->{opts}->exists ($opt) } @{$p}; + my @val = map { $_->{opts}->get ($opt) } @{$p}; + # case (in)sensitivity of an attribute value + my $case = $p->[0]{supportedOpts}{$opt}; + + if ($exists[0] xor $exists[1]) { + push @conflicts, $opt; + } + elsif (defined ($val[0]) xor defined ($val[1])) { + push @conflicts, $opt; + } + elsif (defined ($val[0]) && defined ($val[1])) { + if ($case) { + if ($val[0] ne $val[1]) { + push @conflicts, $opt; + } + } + else { + if (lc ($val[0]) ne lc ($val[1])) { + push @conflicts, $opt; + } + } + } + } + if (@conflicts) { + my $opt = join (", ", @conflicts); + my $origin = join (" and ", map { $_->{origin} } @{$p}); + Base::fatal ("conflicting option(s) '$opt' in $origin"); + } + } + # + # At this point, all config entries strictly match pertaining + # to their respective supported attributes, and can therefore + # be merged to provide a complete loopback device config. + # + for my $c (@conf) { + my @suppOpts = keys (%{$c->{supportedOpts}}); + + for my $opt (@suppOpts) { + my $exists = $c->{opts}->exists ($opt); + my $val = $c->{opts}->get ($opt); + my $case = $c->{supportedOpts}{$opt}; + + next if (! $exists); + if (defined ($case) && (! defined ($val))) { + my $origin = $c->{origin}; + Base::fatal ("missing value for option '$opt' in $origin"); + } + elsif ((! defined ($case)) && defined ($val)) { + my $origin = $c->{origin}; + Base::fatal ("surplus value for option '$opt' in $origin"); + } + if (! exists ($loopOpts{$opt})) { + $loopOpts{$opt} = $val; + } + } + } + + # require fstab or loopaestab entry for loop-AES devices + if (@conf < 2 && defined ($loopOpts{encryption})) { + Base::fatal ("can't find fstab or loopaestab entry for loop-AES device: $name"); + } + + # + # Loopback device attributes specified manually in fstab + # or loopaestab must be checked for mutual compatibility + # and plausible attribute values. + # + if (! defined ($loopOpts{encryption})) { + my @opts = ('gpgkey', 'gpghome', 'gpgmount', 'pseed', 'phash', 'itercountk'); + if (@opts = grep { exists ($loopOpts{$_}) } @opts) { + my $opt = join (', ', @opts); + Base::fatal ("can't use option(s) '$opt' with unencrypted loopback device: $name"); + } + } + if (! defined ($loopOpts{gpgkey})) { + my @opts = ('gpghome', 'gpgmount'); + if (@opts = grep { exists ($loopOpts{$_}) } @opts) { + my $opt = join (', ', @opts); + Base::fatal ("can't use option(s) '$opt' with password encrypted loop-AES device: $name"); + } + if (exists ($loopOpts{multikey})) { + Base::fatal ("multi-key mode loop-AES device requires GPG key: $name"); + } + } + if (defined ($loopOpts{phash})) { + if (! ($loopOpts{phash} =~ /^(sha256|sha384|sha512|rmd160)$/i)) { + my $value = $loopOpts{phash}; + Base::fatal ("unsupported value 'phash=$value' for loop-AES device: $name"); + } + } + if (defined ($loopOpts{itercountk})) { + if (! ($loopOpts{itercountk} =~ /^\d+$/)) { + my $value = $loopOpts{itercountk}; + Base::fatal ("unsupported value 'itercountk=$value' for loop-AES device: $name"); + } + } + + # check existence of GPG key (and optionally GPG home directory) + my $gpgkey = $loopOpts{gpgkey}; + if (defined ($gpgkey)) { + if (! Base::isAbsolute ($gpgkey)) { + Base::fatal ("GPG key file ($gpgkey) not absolute: $name"); + } + if (! (-f $gpgkey)) { + Base::fatal ("GPG key file ($gpgkey) not a regular file: $name"); + } + $gpgkey = Base::canon ($gpgkey); + } + my $gpghome = $loopOpts{gpghome}; + if (defined ($gpghome)) { + if (! Base::isAbsolute ($gpghome)) { + Base::fatal ("GPG home directory ($gpghome) not absolute: $name"); + } + if (! (-d $gpghome)) { + Base::fatal ("GPG home directory ($gpghome) not a directory: $name"); + } + $gpghome = Base::canon ($gpghome); + } + + # + # In case of encryption with a GPG key, there exist + # two different modes of operation: + # + # * If the option 'gpgmount' has been specified, the + # filesystem containing the GPG key file (and optionally + # the GPG home directory) will be mounted at boot time. + # + # * Otherwise, the GPG key file (and optionally the GPG + # home directory) will be copied to the image. + # + + my $gpgkey_mnt = undef; + if (exists ($loopOpts{gpgmount})) { + # choose a unique mount point for each loop device + $gpgkey_mnt = "/key-$name"; + } + + if (defined ($gpgkey) && defined ($gpgkey_mnt)) { + # create GPG key mount point on the image + $actions->add ("gpgmount", $gpgkey_mnt); + + # + # Determine block device of GPG key file, and ensure + # that an optional GPG home directory lies on the same + # filesystem. + # + my $gpgdevno = Base::filedev ($gpgkey); + if (! defined ($gpgdevno)) { + Base::fatal ("can't determine device of GPG key file ($gpgkey): $name"); + } + if (defined ($gpghome)) { + my $n = Base::filedev ($gpghome); + if (! defined ($n)) { + Base::fatal ("can't determine device of GPG home directory ($gpghome): $name"); + } + if (! ($n eq $gpgdevno)) { + Base::fatal ("GPG key file ($gpgkey) and GPG home directory ($gpghome) not on the same filesystem: $name"); + } + } + + # + # Determine the fstab mount point of the block device + # and ensure that the GPG key file (and optionally the + # GPG home directory) really lies on this filesystem. + # + my $gpgfs = FsTab::findByDevno ($gpgdevno); + if (! defined ($gpgfs)) { + Base::fatal ("GPG key ($gpgkey) device not in fstab: $name"); + } + # special handling of root (/) filesystem + (my $mnt = $gpgfs->mnt) =~ s!^/$!!; + if (index ($gpgkey, $mnt . "/") != $[) { + Base::fatal ("GPG key file ($gpgkey) filesystem not found: $name"); + } + if (defined ($gpghome)) { + if (index ($gpghome, $mnt . "/") != $[) { + Base::fatal ("GPG home directory ($gpghome) filesystem not found: $name"); + } + } + + # replace mount points as found at boot time + substr ($gpgkey, $[, length ($mnt), $gpgkey_mnt); + if (defined ($gpghome)) { + substr ($gpghome, $[, length ($mnt), $gpgkey_mnt); + } + + # + # Start and (read-only) mount GPG key device + # + my ($gpgkey_dev, $msg) = $gpgfs->blockDevPath(); + if (! defined ($gpgkey_dev)) { + Base::fatal ($msg); + } + addBlockDevMount ($actions, $gpgkey_dev, $working, $gpgkey_mnt, 0); + } + if (defined ($gpgkey) && (! defined ($gpgkey_mnt))) { + # copy GPG key file (and optionally GPG home directory) to image + if (defined ($gpghome)) { + $actions->add ("gpgpublic", $gpgkey, gpghome => $gpghome); + } + else { + $actions->add ("gpgkey", $gpgkey); + } + } + + # + # Load required modules, ensuring matching kernel and + # userspace loopback support (i.e. native or loop-AES). + # + ModProbe::addModules ($actions, [ "loop" ]); + if (! LoopAesVersion::matchingVersions) { + Base::fatal ("loop kernel module and losetup program versions mismatch"); + } + my $encryption = $loopOpts{encryption}; + if (defined ($encryption)) { + if ($encryption =~ /^(twofish|blowfish|serpent)\d+$/i) { + ModProbe::addModules ($actions, [ "loop_" . lc ($1) ]); + } + elsif (! ($encryption =~ /^(aes\d*|xor)$/i)) { + Base::fatal ("unsupported encryption type ($encryption): '$name'"); + } + } + + # load keymap to allow proper password entry + if (defined ($encryption)) { + $actions->add ("loadkeys", "loadkeys"); + } + + # setup loopback device + $device->setCreator ("losetup"); + $actions->add ("losetup", $device->yspecial, + major => $major, + minor => $minor, + offset => $loopOpts{offset}, + sizelimit => $loopOpts{sizelimit}, + encryption => $loopOpts{encryption}, + loinit => $loopOpts{loinit}, + gpgkey => $gpgkey, + gpghome => $gpghome, + pseed => $loopOpts{pseed}, + phash => $loopOpts{phash}, + itercountk => $loopOpts{itercountk}, + device => $subdev->yspecial, + ); + + # unmount GPG key device if appropriate + if (defined ($gpgkey_mnt)) { + addUnmount ($actions, $gpgkey_mnt); + } + + return 1; +} + # # tryEvms Look if the device could be an evms one # diff -urN yaird-0.0.12.orig/perl/TestSet.pm yaird-0.0.12/perl/TestSet.pm --- yaird-0.0.12.orig/perl/TestSet.pm 2006-10-26 15:41:37.000000000 +0200 +++ yaird-0.0.12/perl/TestSet.pm 2006-10-26 15:45:01.000000000 +0200 @@ -29,6 +29,7 @@ use LvmTab; use Hardware; use RaidTab; +use LoopTab; use EvmsTab; use InputTab; use Image; @@ -132,6 +133,14 @@ } } +sub testLoopDevices () { + print "Loopback devices:\n"; + for my $ld (@{LoopTab::all()}) { + my $str = $ld->string; + print "\t$str\n"; + } +} + sub testEvms () { print "Evms devices:\n"; for my $ev (@{EvmsTab::all()}) { @@ -231,6 +240,7 @@ testLvm (); testHardware (); testRaidDevices(); + testLoopDevices(); testInterpretation (); testInput (); testKconfig (); diff -urN yaird-0.0.12.orig/templates/Debian-initrd.cfg yaird-0.0.12/templates/Debian-initrd.cfg --- yaird-0.0.12.orig/templates/Debian-initrd.cfg 2006-10-26 15:44:48.000000000 +0200 +++ yaird-0.0.12/templates/Debian-initrd.cfg 2006-10-26 15:45:01.000000000 +0200 @@ -300,6 +300,124 @@ END SCRIPT END TEMPLATE + + # + # Load keymap upon boot, allowing proper password entry + # for encrypted devices. + # + TEMPLATE loadkeys + BEGIN + FILE "/bin/loadkeys" + FILE "/bin/gzip" + FILE "/etc/console/boottime.kmap.gz" + SCRIPT "/sbin/init" + BEGIN + !# loadkeys from the kbd package has problems + !# uncompressing the keymap on-the-fly when + !# run from initramfs, don't know why + !gzip -d /etc/console/boottime.kmap.gz + !loadkeys /etc/console/boottime.kmap + END SCRIPT + END TEMPLATE + + + # + # Include GPG program and GPG key file. + # + TEMPLATE gpgkey + BEGIN + FILE "/usr/bin/gpg" + FILE "<TMPL_VAR NAME=target>" + END TEMPLATE + + + # + # Include GPG program, GPG key file and GPG home directory. + # + TEMPLATE gpgpublic + BEGIN + FILE "/usr/bin/gpg" + FILE "<TMPL_VAR NAME=target>" + TREE "<TMPL_VAR NAME=gpghome>" + END TEMPLATE + + + # + # Include GPG program and create GPG key device mount point. + # + TEMPLATE gpgmount + BEGIN + FILE "/usr/bin/gpg" + DIRECTORY "<TMPL_VAR NAME=target>" + END TEMPLATE + + + # + # Setup plain loopback or loop-AES encrypted device. + # + # common losetup arguments: + # - offset + # - device (underlying block device) + # + # loop-AES specific losetup arguments: + # - encryption + # - loinit + # - sizelimit + # - gpgkey + # - gpghome + # - pseed + # - phash + # - itercountk + # + TEMPLATE losetup + BEGIN + FILE "/sbin/losetup" + SCRIPT "/sbin/init" + BEGIN + !mknod <TMPL_VAR NAME=target> b <TMPL_VAR NAME=major> <TMPL_VAR NAME=minor> + !DOCRYPT=1 + !while [ "$DOCRYPT" != "0" ]; do + ! <TMPL_IF NAME=encryption> + ! echo "Encrypted device ('<TMPL_VAR NAME=device>'), please supply passphrase" + ! </TMPL_IF> + ! losetup \ + ! <TMPL_IF NAME=encryption> \ + ! -e <TMPL_VAR NAME=encryption> \ + ! </TMPL_IF> \ + ! <TMPL_IF NAME=loinit> \ + ! -I <TMPL_VAR NAME=loinit> \ + ! </TMPL_IF> \ + ! <TMPL_IF NAME=offset> \ + ! -o <TMPL_VAR NAME=offset> \ + ! </TMPL_IF> \ + ! <TMPL_IF NAME=sizelimit> \ + ! -s <TMPL_VAR NAME=sizelimit> \ + ! </TMPL_IF> \ + ! <TMPL_IF NAME=gpgkey> \ + ! -K <TMPL_VAR NAME=gpgkey> \ + ! <TMPL_IF NAME=gpghome> \ + ! -G <TMPL_VAR NAME=gpghome> \ + ! <TMPL_ELSE> \ + ! -G /nonexistent \ + ! </TMPL_IF> \ + ! </TMPL_IF> \ + ! <TMPL_IF NAME=pseed> \ + ! -S <TMPL_VAR NAME=pseed> \ + ! </TMPL_IF> \ + ! <TMPL_IF NAME=phash> \ + ! -H <TMPL_VAR NAME=phash> \ + ! </TMPL_IF> \ + ! <TMPL_IF NAME=itercountk> \ + ! -C <TMPL_VAR NAME=itercountk> \ + ! </TMPL_IF> \ + ! <TMPL_VAR NAME=target> \ + ! <TMPL_VAR NAME=device> + ! DOCRYPT=$? + !done + END SCRIPT + END TEMPLATE + + # # cryptsetup arguments: # - target diff -urN yaird-0.0.12.orig/templates/Debian.cfg yaird-0.0.12/templates/Debian.cfg --- yaird-0.0.12.orig/templates/Debian.cfg 2006-10-26 15:44:48.000000000 +0200 +++ yaird-0.0.12/templates/Debian.cfg 2006-10-26 15:45:01.000000000 +0200 @@ -329,6 +329,123 @@ # + # Load keymap upon boot, allowing proper password entry + # for encrypted devices. + # + TEMPLATE loadkeys + BEGIN + FILE "/bin/loadkeys" + FILE "/bin/gzip" + FILE "/etc/console/boottime.kmap.gz" + SCRIPT "/init" + BEGIN + !# loadkeys from the kbd package has problems + !# uncompressing the keymap on-the-fly when + !# run from initramfs, don't know why + !gzip -d /etc/console/boottime.kmap.gz + !loadkeys /etc/console/boottime.kmap + END SCRIPT + END TEMPLATE + + + # + # Include GPG program and GPG key file. + # + TEMPLATE gpgkey + BEGIN + FILE "/usr/bin/gpg" + FILE "<TMPL_VAR NAME=target>" + END TEMPLATE + + + # + # Include GPG program, GPG key file and GPG home directory. + # + TEMPLATE gpgpublic + BEGIN + FILE "/usr/bin/gpg" + FILE "<TMPL_VAR NAME=target>" + TREE "<TMPL_VAR NAME=gpghome>" + END TEMPLATE + + + # + # Include GPG program and create GPG key device mount point. + # + TEMPLATE gpgmount + BEGIN + FILE "/usr/bin/gpg" + DIRECTORY "<TMPL_VAR NAME=target>" + END TEMPLATE + + + # + # Setup plain loopback or loop-AES encrypted device. + # + # common losetup arguments: + # - offset + # - device (underlying block device) + # + # loop-AES specific losetup arguments: + # - encryption + # - loinit + # - sizelimit + # - gpgkey + # - gpghome + # - pseed + # - phash + # - itercountk + # + TEMPLATE losetup + BEGIN + FILE "/sbin/losetup" + SCRIPT "/init" + BEGIN + !mknod <TMPL_VAR NAME=target> b <TMPL_VAR NAME=major> <TMPL_VAR NAME=minor> + !DOCRYPT=1 + !while [ "$DOCRYPT" != "0" ]; do + ! <TMPL_IF NAME=encryption> + ! echo "Encrypted device ('<TMPL_VAR NAME=device>'), please supply passphrase" + ! </TMPL_IF> + ! losetup \ + ! <TMPL_IF NAME=encryption> \ + ! -e <TMPL_VAR NAME=encryption> \ + ! </TMPL_IF> \ + ! <TMPL_IF NAME=loinit> \ + ! -I <TMPL_VAR NAME=loinit> \ + ! </TMPL_IF> \ + ! <TMPL_IF NAME=offset> \ + ! -o <TMPL_VAR NAME=offset> \ + ! </TMPL_IF> \ + ! <TMPL_IF NAME=sizelimit> \ + ! -s <TMPL_VAR NAME=sizelimit> \ + ! </TMPL_IF> \ + ! <TMPL_IF NAME=gpgkey> \ + ! -K <TMPL_VAR NAME=gpgkey> \ + ! <TMPL_IF NAME=gpghome> \ + ! -G <TMPL_VAR NAME=gpghome> \ + ! <TMPL_ELSE> \ + ! -G /nonexistent \ + ! </TMPL_IF> \ + ! </TMPL_IF> \ + ! <TMPL_IF NAME=pseed> \ + ! -S <TMPL_VAR NAME=pseed> \ + ! </TMPL_IF> \ + ! <TMPL_IF NAME=phash> \ + ! -H <TMPL_VAR NAME=phash> \ + ! </TMPL_IF> \ + ! <TMPL_IF NAME=itercountk> \ + ! -C <TMPL_VAR NAME=itercountk> \ + ! </TMPL_IF> \ + ! <TMPL_VAR NAME=target> \ + ! <TMPL_VAR NAME=device> + ! DOCRYPT=$? + !done + END SCRIPT + END TEMPLATE + + + # # cryptsetup arguments: # - target # - cipher diff -urN yaird-0.0.12.orig/templates/Fedora.cfg yaird-0.0.12/templates/Fedora.cfg --- yaird-0.0.12.orig/templates/Fedora.cfg 2006-10-26 15:44:48.000000000 +0200 +++ yaird-0.0.12/templates/Fedora.cfg 2006-10-26 15:45:01.000000000 +0200 @@ -340,6 +340,123 @@ # + # Load keymap upon boot, allowing proper password entry + # for encrypted devices. + # + TEMPLATE loadkeys + BEGIN + FILE "/bin/loadkeys" + FILE "/bin/gzip" + FILE "/etc/console/boottime.kmap.gz" + SCRIPT "/init" + BEGIN + !# loadkeys from the kbd package has problems + !# uncompressing the keymap on-the-fly when + !# run from initramfs, don't know why + !gzip -d /etc/console/boottime.kmap.gz + !loadkeys /etc/console/boottime.kmap + END SCRIPT + END TEMPLATE + + + # + # Include GPG program and GPG key file. + # + TEMPLATE gpgkey + BEGIN + FILE "/usr/bin/gpg" + FILE "<TMPL_VAR NAME=target>" + END TEMPLATE + + + # + # Include GPG program, GPG key file and GPG home directory. + # + TEMPLATE gpgpublic + BEGIN + FILE "/usr/bin/gpg" + FILE "<TMPL_VAR NAME=target>" + TREE "<TMPL_VAR NAME=gpghome>" + END TEMPLATE + + + # + # Include GPG program and create GPG key device mount point. + # + TEMPLATE gpgmount + BEGIN + FILE "/usr/bin/gpg" + DIRECTORY "<TMPL_VAR NAME=target>" + END TEMPLATE + + + # + # Setup plain loopback or loop-AES encrypted device. + # + # common losetup arguments: + # - offset + # - device (underlying block device) + # + # loop-AES specific losetup arguments: + # - encryption + # - loinit + # - sizelimit + # - gpgkey + # - gpghome + # - pseed + # - phash + # - itercountk + # + TEMPLATE losetup + BEGIN + FILE "/sbin/losetup" + SCRIPT "/init" + BEGIN + !mknod <TMPL_VAR NAME=target> b <TMPL_VAR NAME=major> <TMPL_VAR NAME=minor> + !DOCRYPT=1 + !while [ "$DOCRYPT" != "0" ]; do + ! <TMPL_IF NAME=encryption> + ! echo "Encrypted device ('<TMPL_VAR NAME=device>'), please supply passphrase" + ! </TMPL_IF> + ! losetup \ + ! <TMPL_IF NAME=encryption> \ + ! -e <TMPL_VAR NAME=encryption> \ + ! </TMPL_IF> \ + ! <TMPL_IF NAME=loinit> \ + ! -I <TMPL_VAR NAME=loinit> \ + ! </TMPL_IF> \ + ! <TMPL_IF NAME=offset> \ + ! -o <TMPL_VAR NAME=offset> \ + ! </TMPL_IF> \ + ! <TMPL_IF NAME=sizelimit> \ + ! -s <TMPL_VAR NAME=sizelimit> \ + ! </TMPL_IF> \ + ! <TMPL_IF NAME=gpgkey> \ + ! -K <TMPL_VAR NAME=gpgkey> \ + ! <TMPL_IF NAME=gpghome> \ + ! -G <TMPL_VAR NAME=gpghome> \ + ! <TMPL_ELSE> \ + ! -G /nonexistent \ + ! </TMPL_IF> \ + ! </TMPL_IF> \ + ! <TMPL_IF NAME=pseed> \ + ! -S <TMPL_VAR NAME=pseed> \ + ! </TMPL_IF> \ + ! <TMPL_IF NAME=phash> \ + ! -H <TMPL_VAR NAME=phash> \ + ! </TMPL_IF> \ + ! <TMPL_IF NAME=itercountk> \ + ! -C <TMPL_VAR NAME=itercountk> \ + ! </TMPL_IF> \ + ! <TMPL_VAR NAME=target> \ + ! <TMPL_VAR NAME=device> + ! DOCRYPT=$? + !done + END SCRIPT + END TEMPLATE + + + # # cryptsetup arguments: # - target # - cipher