[arch-projects] [RFC 00/23] Encrypted volume work
From: Matthew Monaco <matthew.monaco@0x01b.net> I worked with Dave and Tom this past weekend to clean up and enhance encrypted volume handling. There are quite a few "patches" here, and more to come against initscripts. All of this fixes a handful of bugs, adds new features, does some refactoring. In summary, I wrote a new package called 'cryptmount.' The intention is for it to depend on cryptsetup and to provide the encrypt hooks for mkinitcpio. Additionally initscripts will depend on cryptmount (optdepends will work too). The cryptmount code is here [1] and the initscripts changes are here [2]. There are a few goals: 1) Use the same code for the mkinitcpio encrypt hook and initscripts. 2) Allow for interoperability with systemd's crypttab format. This is accomplished without any forced changes on the user (with the exception of plaintext passwords in crypttab). 3) Allow the random seed to be restored before doing things like setting up a swap volume which uses /dev/urandom as a password. 4) If possible, allow for encrypted /usr from the initrd. This depends on Dave's working branch of mkinitcpio which provides late hooks (and cleanup hooks). *5*) Do not drop support for current configurations. This is important. The only thing that is dropped is storing a plain text password in crypttab. Whether your options line in crypttab is literally for cryptsetup (--size=100 --cipher=...) or a comma separated list (size=100,cipher=...), your configuration will be supported. That said, if you see any holes in this statement, please let me know and I will address it. This addresses the following bugs, there may be more, and you may question that it does for some of these: FS#17131 - Restore random seed before using decryption FS#24700 - Allow UUID for cryptdevice In addition we support UUID,PARTUUID,LABEL for both the encrypted device AND the passphrase if it is on an external device. FS#27137 - I think a dup of the above. FS#23182 - Multiple device support for the initrd The encrypt hook included supports root, /usr, and an arbitrary number of encrypted mappings. FS#15738 - More or less similar to above FS#21936 - Don't immediately revert to interactive pw if key device is not available. All devices are resolved and waited on IFF udevd is running. This goes for the initrd and rc.sysinit. FS#21198 - Mount key devices if needed. This is done whenever the key is a file on another device and that device is not already mounted. FS#21513 - Provide a man page for crypttab. I wrote one and for cryptmount. I have been testing this for the past week, but I'm sure there are some bugs. Please report any problems you see (or experience if you are able to test). Also, if you see an opportunity for improvements in efficiency, cleanup, or additional functionality, let me know. [1] https://github.com/mmonaco/cryptmount/tree/master [2] https://github.com/mmonaco/initscripts/tree/crypto -- 1.7.10.2
From: Matthew Monaco <matthew.monaco@0x01b.net> --- cryptmount.sh | 122 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 122 insertions(+) diff --git a/cryptmount.sh b/cryptmount.sh index e69de29..dacfc1a 100755 --- a/cryptmount.sh +++ b/cryptmount.sh @@ -0,0 +1,122 @@ +#!/bin/sh + +SHORTOPTS="LMUc:w:nqvho:O:" + +LOGLEVEL=1 +DRYRUN=0 +WAITTIME=10 +CRYPTTAB=/etc/crypttab +OPTIONS= +FILTER="!noauto" + +ct_print_usage() { + cat <<__EOF__ +usage: $0 [OPTIONS] [-L] + $0 [OPTIONS] -M [NAME|DEVICE] + $0 [OPTIONS] -M NAME DEVICE [KEY] + $0 [OPTIONS] -U [NAME[,...]] + + List, map, and unmap encrypted volumes. The utility is a wrapper for + cryptsetup which makes use of a crypttab file. + + actions: + -L list the names of volumes defined in crypttab, this is + the default + -M map a volume defined in crypttab or defined on the command + line. with no arguments, map all volumes without the noauto + option + -U unmap volumes defined in crypttab. with no arguments, unmap + all volumes without the noauto option + + options: + -c FILE set the crypttab location (default: /etc/crypttab) + -w NUM wait time (seconds) for a device if it is not already available + -n dry run + -q decrease verbosity + -v increase verbosity + -h print this message + -o OPT[,...] + options which are appened to the options defined in crypttab + (they take precedence). specifying this multiple times is + cumulative + -O OPT[,...] + filter used *only* when no volumes are given on the command + line. an option may start with a ! to require that it must not + be present. specifying this multiple times is cumulative + +__EOF__ + exit $1 +} + +# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ # +# # +# Main functions # +# # + +ct_main() { + + local action + + set_action() { + if [ -z $action ]; then + action="$@" + else + error "only one of -L, -M, or -U may be given" + ct_print_usage 1 + fi + } + + while getopts ":$SHORTOPTS" opt ; do + + case $opt in + L) set_action list;; + M) set_action map;; + U) set_action unmap;; + c) CRYPTTAB="$OPTARG";; + w) WAITTIME=${OPTARG//[!0-9]};; + n) DRYRUN=1;; + q) LOGLEVEL=$(( LOGLEVEL - 1 ));; + v) LOGLEVEL=$(( LOGLEVEL + 1 ));; + h) ct_print_usage 0;; + o) OPTIONS="$OPTIONS,$OPTARG";; + O) FILTER="$FILTER,$OPTARG";; + :) + error "option requires an argument -- '$OPTARG'" + ct_print_usage 1 + ;; + ?) + error "invalid option -- '$OPTARG'" + ct_print_usage 1 + ;; + esac + + done + + shift $(( OPTIND - 1 )) + + if [ -z "$action" -o "$action" = "list" ]; then + + : + + elif [ "$action" = "unmap" ]; then + + : + + elif [ "$action" = "map" ]; then + + : + + else + + error "Internal error: no action" + false + + fi +} + +# # +# ---------------------------------------------------------------------------- # + +ct_main "$@" + +# vim: set ft=sh noet ts=2 sw=2 : -- 1.7.10.2
From: Matthew Monaco <matthew.monaco@0x01b.net> How can I get the diff better here? --- cryptmount.sh | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/cryptmount.sh b/cryptmount.sh index dacfc1a..bd3ed86 100755 --- a/cryptmount.sh +++ b/cryptmount.sh @@ -50,6 +50,46 @@ __EOF__ # ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ # # # +# Utilities # +# # + +error() { + [ $LOGLEVEL -ge 0 ] && printf "E: %s\n" "$*" >&2 || true +} + +die() { + printf "E: %s\n" "$*" >&2 + exit ${1:-1} +} + +warn() { + [ $LOGLEVEL -ge 1 ] && printf "W: %s\n" "$*" >&2 || true +} + +msg() { + [ $LOGLEVEL -ge 1 ] && printf "M: %s\n" "$*" >&2 || true +} + +info() { + [ $LOGLEVEL -ge 2 ] && printf "I: %s\n" "$*" >&2 || true +} + +run() { + [ $LOGLEVEL -ge 2 ] && printf "R: %s\n" "$*" >&2 + if [ $DRYRUN -eq 1 ]; then + true + else + "$@" + fi +} + +trim() { + local IFS=$' \t\n' + echo -n $* +} + +# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ # +# # # Main functions # # # -- 1.7.10.2
From: Matthew Monaco <matthew.monaco@0x01b.net> I don't really like this, it would be better to check only for cryptsetup here, other checks can go where they're used or not at all. The best might be to not do anything like this at all. --- cryptmount.sh | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/cryptmount.sh b/cryptmount.sh index bd3ed86..fa25fdf 100755 --- a/cryptmount.sh +++ b/cryptmount.sh @@ -1,6 +1,7 @@ #!/bin/sh SHORTOPTS="LMUc:w:nqvho:O:" +DEPS="cryptsetup blkid findmnt mkswap mktemp" LOGLEVEL=1 DRYRUN=0 @@ -134,6 +135,11 @@ ct_main() { shift $(( OPTIND - 1 )) + # Warn if any of the dependencies are missing + for dep in $DEPS; do + type $dep &> /dev/null || info "$dep not found, some functionality may fail" + done + if [ -z "$action" -o "$action" = "list" ]; then : -- 1.7.10.2
On Fri, May 18, 2012 at 6:21 PM, Matthew Monaco <dgbaley27@0x01b.net> wrote:
I don't really like this, it would be better to check only for cryptsetup here, other checks can go where they're used or not at all.
The best might be to not do anything like this at all.
I'm not a big fan of this. Just deal with errors properly where they might happen (as other things than a missing binary might go wrong). If you are confident that this warning will give no false positives (i.e. warn about missing stuff which actually does not matter), then it's fine, but I don't think it is worth the effort. -t
On 05/18/2012 04:09 PM, Tom Gundersen wrote:
On Fri, May 18, 2012 at 6:21 PM, Matthew Monaco <dgbaley27@0x01b.net> wrote:
I don't really like this, it would be better to check only for cryptsetup here, other checks can go where they're used or not at all.
The best might be to not do anything like this at all.
I'm not a big fan of this. Just deal with errors properly where they might happen (as other things than a missing binary might go wrong).
If you are confident that this warning will give no false positives (i.e. warn about missing stuff which actually does not matter), then it's fine, but I don't think it is worth the effort.
-t
(Given the commit message) that's enough convincing for me =)
From: Matthew Monaco <matthew.monaco@0x01b.net> ct_check_filter - Compare $FILTER (-O) to an optlist. If a token from filter starts with !opt, then "opt" must not be in optlist. Other than somewhat emulating mount here, later we'll allow options to have a % prefix, for example %usb will allow -O %usb to map all volumes with the %usb tag. We'll add an implicit tag called %random for devices which use /dev/urandom or /dev/random as a key. This will allow -O !%random to be done before the random seed is restored an -O %random afterwards. Of course, %random may also be specified expliticly in crypttab. ct_read_crypttab - Feed each line of /etc/crypttab to a function. each line is divided into a name, device, key, and options. ct_check_filter is applied to the options and if ok, the 4 fields are passed to the function. All operations that require reading crypttab will use this There is also a -1 option for ct_read_crypttab to exit after the first successful call to the function, this will be useful for identifying a specific volume. Co-authored-by: Dave Reisner <dreisner@archlinux.org> --- cryptmount.sh | 105 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) diff --git a/cryptmount.sh b/cryptmount.sh index fa25fdf..03b8575 100755 --- a/cryptmount.sh +++ b/cryptmount.sh @@ -160,6 +160,111 @@ ct_main() { fi } + +# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ # +# # +# Functions for iterating over crypttab # +# # + +ct_read_crypttab() { + + if [ ! -f "$CRYPTTAB" -o ! -r "$CRYPTTAB" ]; then + error "cannot read $CRYPTTAB" + return 1 + fi + + local func="$@" line lineno=0 name dev key options ret=0 adhoc=0 + + if [ "$1" = "-1" ]; then + adhoc=1 + shift + func="$@" + fi + + while read -r name dev key options <&3; do + + lineno=$(( lineno + 1 )) + [ -z "$name" ] || [ ${name:0:1} = "#" ] && continue + + # unescape devname and keyname + name=$(printf '%b' "$name") + dev=$(printf '%b' "$dev") + key=$(printf '%b' "$key") + + if [ -z "$name" ]; then + warn "$CRYPTTAB:$lineno: the name (first column) cannot be blank" + continue + elif [ -z "$dev" ]; then + warn "$CRYPTTAB:$lineno: the device (second column) cannot be blank" + continue + fi + + case $key in + -|none|"") + key=- + ;; + /*|UUID=*|PARTUUID=*|LABEL=*) + : + ;; + *) + warn "$CRYPTTAB:$lineno: plain text keys are not supported" + key=- + ;; + esac + + if ct_check_filter $options; then + if ! $func "$name" "$dev" "$key" $options; then + ret=$(( ret + 1 )) + elif [ $adhoc -eq 1 ]; then + ret=0 + break + fi + fi + + done 3< "$CRYPTTAB" + + return $ret +} + +ct_check_filter() { + + local IFS=$',' fltr opt + + for fltr in $FILTER; do + fltr="$(trim $fltr)" + [ -z "$fltr" ] && continue + + if [ "x${fltr:0:1}" != "x!" ]; then + + for opt in $*; do + opt="$(trim $opt)" + [ -z "$opt" ] && continue + + if [ "$fltr" = "$opt" -o "$fltr" = "${opt%%=*}" ]; then + continue 2 + fi + done + + return 1 + + else + + for opt in $*; do + opt="$(trim $opt)" + [ -z "$opt" ] && continue + + if [ "$fltr" = "!$opt" -o "$fltr" = "!${opt%%=*}" ]; then + return 1 + fi + done + + fi + + done + + return 0 +} + # # # ---------------------------------------------------------------------------- # -- 1.7.10.2
From: Matthew Monaco <matthew.monaco@0x01b.net> --- cryptmount.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cryptmount.sh b/cryptmount.sh index 03b8575..41b713c 100755 --- a/cryptmount.sh +++ b/cryptmount.sh @@ -203,6 +203,9 @@ ct_read_crypttab() { -|none|"") key=- ;; + /dev/random|/dev/urandom) + options="$options,%random" + ;; /*|UUID=*|PARTUUID=*|LABEL=*) : ;; -- 1.7.10.2
On Fri, May 18, 2012 at 6:21 PM, Matthew Monaco <dgbaley27@0x01b.net> wrote:
From: Matthew Monaco <matthew.monaco@0x01b.net>
--- cryptmount.sh | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/cryptmount.sh b/cryptmount.sh index 03b8575..41b713c 100755 --- a/cryptmount.sh +++ b/cryptmount.sh @@ -203,6 +203,9 @@ ct_read_crypttab() { -|none|"") key=- ;; + /dev/random|/dev/urandom) + options="$options,%random" + ;;
You probably want to tag /dev/hw_random as well, in case someone decides to use a real random generator.
/*|UUID=*|PARTUUID=*|LABEL=*) : ;; -- 1.7.10.2
From: Matthew Monaco <matthew.monaco@0x01b.net> --- cryptmount.sh | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/cryptmount.sh b/cryptmount.sh index 41b713c..47b3ac6 100755 --- a/cryptmount.sh +++ b/cryptmount.sh @@ -142,7 +142,12 @@ ct_main() { if [ -z "$action" -o "$action" = "list" ]; then - : + if [ $# -ne 0 ]; then + warn "With -L, volumes given on the command line have no effect" + fi + + list_func() { printf "%s\n" "$1"; } + ct_read_crypttab list_func elif [ "$action" = "unmap" ]; then -- 1.7.10.2
From: Matthew Monaco <matthew.monaco@0x01b.net> Without any arguments, use crypttab. Otherwise try to unmap whatever is given on the command line. This does not support automatically unmapping volumes which are not in crypttab. One FIXME might be that when using crypttab, volumes should be handled in the reverse order. --- cryptmount.sh | 44 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/cryptmount.sh b/cryptmount.sh index 47b3ac6..bdfd1a1 100755 --- a/cryptmount.sh +++ b/cryptmount.sh @@ -151,7 +151,13 @@ ct_main() { elif [ "$action" = "unmap" ]; then - : + if [ $# -gt 0 ]; then + [ "$FILTER" != "!noauto" ] && \ + info "Filters from -O are ignored in this mode" + unset FILTER + fi + + ct_main_unmap "$@" elif [ "$action" = "map" ]; then @@ -165,6 +171,25 @@ ct_main() { fi } +ct_main_unmap() { + + if [ $# -eq 0 ]; then + + ct_read_crypttab ct_unmap + + else + + local vol ret=0 + + for vol in "$@"; do + ct_unmap "$vol" || ret=$(( ret+1 )) + done + + return $ret + + fi +} + # ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ # # # @@ -273,6 +298,23 @@ ct_check_filter() { return 0 } +# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ # +# # +# Mapping, unmapping, finding stuff # +# # + +ct_unmap() { + local name="$1" + if [ ! -e "/dev/mapper/$name" ]; then + warn "Volume was not mapped (no '/dev/mapper/$name')" + elif run cryptsetup remove "$name"; then + info "$name unmapped" + else + error "failed to unmap $name" + false + fi +} + # # # ---------------------------------------------------------------------------- # -- 1.7.10.2
On Fri, May 18, 2012 at 6:22 PM, Matthew Monaco <dgbaley27@0x01b.net> wrote:
From: Matthew Monaco <matthew.monaco@0x01b.net>
Without any arguments, use crypttab. Otherwise try to unmap whatever is given on the command line. This does not support automatically unmapping volumes which are not in crypttab.
One FIXME might be that when using crypttab, volumes should be handled in the reverse order.
Hopefully the order should not matter (except when encrypting encrypted devices!), but I agree that in principle -U should be the dual of the normal operation so doing the unmappings in reverse makes the most sense. -t
From: Matthew Monaco <matthew.monaco@0x01b.net> Without udevd, it is unlikely that new devices are going to show up. So we will know not to wait for them. Suggested-by: Dave Reisner <dreisner@archlinux.org> --- cryptmount.sh | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/cryptmount.sh b/cryptmount.sh index bdfd1a1..88771bc 100755 --- a/cryptmount.sh +++ b/cryptmount.sh @@ -2,6 +2,7 @@ SHORTOPTS="LMUc:w:nqvho:O:" DEPS="cryptsetup blkid findmnt mkswap mktemp" +UDEVRUNNING=0 LOGLEVEL=1 DRYRUN=0 @@ -140,6 +141,14 @@ ct_main() { type $dep &> /dev/null || info "$dep not found, some functionality may fail" done + # Check for UDEV + if pidof udevd &>/dev/null; then + UDEVRUNNING=1 + info "Detected udevd" + else + info "udevd not running, or unable to detect it: waiting for devices disabled" + fi + if [ -z "$action" -o "$action" = "list" ]; then if [ $# -ne 0 ]; then -- 1.7.10.2
On Fri, May 18, 2012 at 6:22 PM, Matthew Monaco <dgbaley27@0x01b.net> wrote:
Without udevd, it is unlikely that new devices are going to show up. So we will know not to wait for them.
Suggested-by: Dave Reisner <dreisner@archlinux.org>
NACK. I'm probably missing the point here (as I was a bit suspicious about waiting for devices in the first place), but I don't think this makes sense. Two cases where a missing udev means you won't get more devices: 1) If you reference them by symlinks in /dev/disks/by-* 2) If the required module is not built in to the kernel and udev is needed for modprobing it. However, you might very well have built your usb-drivers into the kernel, referenced them as /dev/sdc1 (or whatever) and need to wait for them to appear. Remember that udev no longer populates /dev with devicenodes as this is done by the kernel. Am I missing something? -t
From: Matthew Monaco <matthew.monaco@0x01b.net> This will be for the encrypted device and if the key is a file on an external device. --- cryptmount.sh | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/cryptmount.sh b/cryptmount.sh index 88771bc..55a6944 100755 --- a/cryptmount.sh +++ b/cryptmount.sh @@ -324,6 +324,41 @@ ct_unmap() { fi } +ct_resolve_device() { + + local tmp="" device="$1" seconds=$WAITTIME tag tagval + + case "$device" in + UUID=*|PARTUUID=*|LABEL=*) + tmp="$(blkid -l -o device -t "$device")" + if [ -z "$tmp" ]; then + if [ $UDEVRUNNING -eq 1 ]; then + tag="$(awk -v t="${device%%=*}" 'BEGIN { print tolower(t) }')" + tagval="${device#*=}" + device="/dev/disk/by-$tag/$tagval" + fi + else + device="$tmp" + fi + esac + + if [ ! -e "$device" -a "${device:0:5}" = "/dev/" -a "$UDEVRUNNING" -eq 1 ]; then + msg "Waiting $seconds seconds for '$device'..." + until [ -e "$device" -o $seconds -eq 0 ]; do + sleep 1 + seconds=$(( seconds - 1 )) + done + fi + + printf "%s" "$device" + + if [ -e "$device" ]; then + info "resolve: found '$device'" + else + error "resolve: unable to find '$device'" + return 1 + fi +} # # # ---------------------------------------------------------------------------- # -- 1.7.10.2
From: Matthew Monaco <matthew.monaco@0x01b.net> As far as the structure of the rest of the code goes, this one is a little different because it sets the 'args' and 'swap' variables. I'd like a cleaner way to do this. With the exception of some special values, convert the comma separated list of options to pass directly to cryptsetup. This means we don't have to explicitly support all of cryptsetups options. 'size' and 'device-size' are needed because (yes) systemd and Debian use size for cryptsetup's --key-size option. "cryptsetup --size create" limits the size of a device. 'swap' means run mkswap after mounting, this is standard as far as the Debian and systemd format goes. 'luks' and 'plain' are also used by Debian and systemd, but they seem like superfluous configuration because "cryptsetup isLuks" gives this information. 'noauto' will work with the default $FILTER (-O) of !noauto 'tmp' is supported by Debian and systemd. This will come in a later commit. There is also list of options which are supported by Debian that we'll ignore. --- cryptmount.sh | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/cryptmount.sh b/cryptmount.sh index 55a6944..7e89bbc 100755 --- a/cryptmount.sh +++ b/cryptmount.sh @@ -149,6 +149,17 @@ ct_main() { info "udevd not running, or unable to detect it: waiting for devices disabled" fi + # Pre-parse OPTIONS, a little ugly, but it works + preparse() { + local args swap + if ! ct_parse_options $OPTIONS; then + error "Invalid options string: $OPTIONS" + exit 1 + fi + OPTIONS="$args" + } + preparse + if [ -z "$action" -o "$action" = "list" ]; then if [ $# -ne 0 ]; then @@ -359,6 +370,64 @@ ct_resolve_device() { return 1 fi } + +ct_parse_options() { + + local IFS=',' optlst="$*" opt key val + + for opt in $optlst; do + + # separate key and value + unset key val + case "$opt" in + "") + continue;; + *=*) + key="${opt%%=*}" + val="${opt#*=}" + [ "$key" = "$val" ] && unset val + ;; + *) + key="$opt";; + esac + + case "$key" in + swap) + # set external variable + swap=1 + ;; + luks|plain) + warn "Ignoring option $key, LUKS volumes are automatically detected" + ;; + noauto|%*) + : + ;; + skip|precheck|check|checkargs|noearly|loud|keyscript) + warn "Ignoring Debian specific option '$key'" + ;; + tmp) + warn "The tmp= option is not supported" + ;; + size) + args="$args --key-size $val" + ;; + device-size) + args="$args --size $val" + ;; + *) + if [ ${#key} -eq 1 ]; then + args="$args -$key $val" + else + args="$args --$key $val" + fi + ;; + esac + + done + + return 0 +} + # # # ---------------------------------------------------------------------------- # -- 1.7.10.2
On Fri, May 18, 2012 at 6:22 PM, Matthew Monaco <dgbaley27@0x01b.net> wrote:
With the exception of some special values, convert the comma separated list of options to pass directly to cryptsetup. This means we don't have to explicitly support all of cryptsetups options.
If at all possible, I think it is better to explicitly handle the things we want to support. Passing on the options blindly means that we are tightly coupled to the underlying tool (which is for instance what made the transition from net-tools to iproute so painful). Maybe one solution could be to handle the things we want to support, and for the sake of backwards compatibility we do your catch-all matching at the end, but print a warning "Passing unrecognized options to cryptsetup"?
'size' and 'device-size' are needed because (yes) systemd and Debian use size for cryptsetup's --key-size option. "cryptsetup --size create" limits the size of a device.
'swap' means run mkswap after mounting, this is standard as far as the Debian and systemd format goes.
'luks' and 'plain' are also used by Debian and systemd, but they seem like superfluous configuration because "cryptsetup isLuks" gives this information.
'noauto' will work with the default $FILTER (-O) of !noauto
'tmp' is supported by Debian and systemd. This will come in a later commit.
There is also list of options which are supported by Debian that we'll ignore.
It should be pointed out that in this context "Debian+systemd" essentially means "everyone else". Also, we don't "need" to deal with these options, but I absolutely agree that we should (even if all we do is warn that the option is not supported). I think we should aim for: 1) a crypttab file copied from another distro to Arch should do something sensible (hopefully work, but at least give reasonable error messages) and 2) a crypttab file that works without warnings on Arch should work just fine when copied to another distro.
--- cryptmount.sh | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+)
diff --git a/cryptmount.sh b/cryptmount.sh index 55a6944..7e89bbc 100755 --- a/cryptmount.sh +++ b/cryptmount.sh @@ -149,6 +149,17 @@ ct_main() { info "udevd not running, or unable to detect it: waiting for devices disabled" fi
+ # Pre-parse OPTIONS, a little ugly, but it works + preparse() { + local args swap + if ! ct_parse_options $OPTIONS; then + error "Invalid options string: $OPTIONS" + exit 1 + fi + OPTIONS="$args" + } + preparse + if [ -z "$action" -o "$action" = "list" ]; then
if [ $# -ne 0 ]; then @@ -359,6 +370,64 @@ ct_resolve_device() { return 1 fi } + +ct_parse_options() { + + local IFS=',' optlst="$*" opt key val + + for opt in $optlst; do + + # separate key and value + unset key val + case "$opt" in + "") + continue;; + *=*) + key="${opt%%=*}" + val="${opt#*=}" + [ "$key" = "$val" ] && unset val + ;; + *) + key="$opt";; + esac + + case "$key" in + swap) + # set external variable + swap=1 + ;; + luks|plain) + warn "Ignoring option $key, LUKS volumes are automatically detected" + ;; + noauto|%*) + : + ;; + skip|precheck|check|checkargs|noearly|loud|keyscript) + warn "Ignoring Debian specific option '$key'" + ;; + tmp) + warn "The tmp= option is not supported" + ;; + size) + args="$args --key-size $val" + ;; + device-size) + args="$args --size $val" + ;; + *) + if [ ${#key} -eq 1 ]; then + args="$args -$key $val" + else + args="$args --$key $val" + fi + ;; + esac + + done + + return 0 +} + # # # ---------------------------------------------------------------------------- #
-- 1.7.10.2
From: Matthew Monaco <matthew.monaco@0x01b.net> This is needed so we don't break existing configs. The approach here is to allow these intermixed with the comma separated key=value pairs. --- cryptmount.sh | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/cryptmount.sh b/cryptmount.sh index 7e89bbc..e86323b 100755 --- a/cryptmount.sh +++ b/cryptmount.sh @@ -373,7 +373,7 @@ ct_resolve_device() { ct_parse_options() { - local IFS=',' optlst="$*" opt key val + local IFS=',' optlst="$*" opt key val depr=0 for opt in $optlst; do @@ -382,6 +382,17 @@ ct_parse_options() { case "$opt" in "") continue;; + -*) + if [ $depr -eq 0 ]; then + info "You are using a deprecated format for the options field. The entire" + info " field will be passed directly to cryptsetup. Please use the more" + info " standardized comma-deliminated options list instead. This format" + info " will be removed in a future version of cryptmount/crypttab!" + depr=1 + fi + args="$args $opt" + continue + ;; *=*) key="${opt%%=*}" val="${opt#*=}" -- 1.7.10.2
From: Matthew Monaco <matthew.monaco@0x01b.net> Resolve device, parse options, run cryptsetup and run mkswap if needed --- cryptmount.sh | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/cryptmount.sh b/cryptmount.sh index e86323b..d602043 100755 --- a/cryptmount.sh +++ b/cryptmount.sh @@ -335,6 +335,72 @@ ct_unmap() { fi } +ct_map() { + +<<<<<<< HEAD + local name="$1" dev="$2" key="$3" args="" swap=0 + shift 3 + + if [ -e "/dev/mapper/$name" ]; then + error "Volume is already mapped ('/dev/mapper/$name' exists')" + return 1 + fi + + # this function sets the args and swap variables + if ! ct_parse_options "$@"; then + error "Unable to parse options" + return 1 + fi + args="$args $OPTIONS" + + # resolve the encrypted device, can't do much without this + if ! dev="$(ct_resolve_device "$dev")"; then + error "device '$dev' not found" + return 1 + fi + + if [ "$key" ]; then + key="--key-file=\"$key\"" + fi + + local ret=0 + + # the main event, run cryptsetup (and mkswap, mkfs if necessary) + if cryptsetup isLuks "$dev"; then + + info "device '$dev' detected as LUKS" + + if run cryptsetup luksOpen $key $args "$dev" "$name"; then + info "sucessfully mapped '$dev' to '/dev/mapper/$name'" + else + error "unable to map '$dev' to '/dev/mapper/$name'" + ret=1 + fi + + else + + info "device '$dev' assumed to be plain" + + if run cryptsetup create $key $args "$name" "$dev"; then + info "sucessfully mapped '$dev' to '/dev/mapper/$name'" + if [ $swap -eq 1 ]; then + if run mkswap -f -L "$name" "/dev/mapper/$name"; then + info "mkswap successful on '/dev/mapper/$name'" + else + error "mkswap failed for '/dev/mapper/$name'" + ret=1 + fi + fi + else + error "unable to map '$dev' to '/dev/maper/name/$name'" + ret=1 + fi + + fi + + return $ret +} + ct_resolve_device() { local tmp="" device="$1" seconds=$WAITTIME tag tagval -- 1.7.10.2
From: Matthew Monaco <matthew.monaco@0x01b.net> Currently in rc.sysinit we check that blkid returns 2 before running mkswap. This is a little bit stronger. Even without mkswap "cryptsetup create" can be dangerous, so do the blkid check for all plain (non-LUKS) mappings. Furthermore, just check for a non-zero return status, if this is too broad we can get more specific. Note: A user can still destroy her data if she enters the wrong password for a cryptsetup create. This we'll leave as the user's fault; she should be aware of the limitations of a plain mapping and the --verify-passphrase cryptsetup option. --- cryptmount.sh | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/cryptmount.sh b/cryptmount.sh index d602043..03699d0 100755 --- a/cryptmount.sh +++ b/cryptmount.sh @@ -1,6 +1,6 @@ #!/bin/sh -SHORTOPTS="LMUc:w:nqvho:O:" +SHORTOPTS="LMUc:fw:nqvho:O:" DEPS="cryptsetup blkid findmnt mkswap mktemp" UDEVRUNNING=0 @@ -10,6 +10,7 @@ WAITTIME=10 CRYPTTAB=/etc/crypttab OPTIONS= FILTER="!noauto" +FORCE=0 ct_print_usage() { cat <<__EOF__ @@ -32,6 +33,8 @@ usage: $0 [OPTIONS] [-L] options: -c FILE set the crypttab location (default: /etc/crypttab) + -f force destructive operations even when a block device appears to + contain data -w NUM wait time (seconds) for a device if it is not already available -n dry run -q decrease verbosity @@ -115,6 +118,7 @@ ct_main() { M) set_action map;; U) set_action unmap;; c) CRYPTTAB="$OPTARG";; + f) FORCE=1;; w) WAITTIME=${OPTARG//[!0-9]};; n) DRYRUN=1;; q) LOGLEVEL=$(( LOGLEVEL - 1 ));; @@ -381,7 +385,14 @@ ct_map() { info "device '$dev' assumed to be plain" - if run cryptsetup create $key $args "$name" "$dev"; then + # cryptsetup 'create' can be destructive, don't do it if blkid can + # identify the device type + if [ $FORCE -ne 1 ] && blkid -p "$dev" &>/dev/null; then + error "Refusing to call 'cryptsetup create' on device that might" + error " have data. If you are sure this is what you want, use" + error " the -f option" + ret=1 + elif run cryptsetup create $key $args "$name" "$dev"; then info "sucessfully mapped '$dev' to '/dev/mapper/$name'" if [ $swap -eq 1 ]; then if run mkswap -f -L "$name" "/dev/mapper/$name"; then -- 1.7.10.2
On Fri, May 18, 2012 at 6:22 PM, Matthew Monaco <dgbaley27@0x01b.net> wrote:
Currently in rc.sysinit we check that blkid returns 2 before running mkswap. This is a little bit stronger. Even without mkswap "cryptsetup create" can be dangerous, so do the blkid check for all plain (non-LUKS) mappings. Furthermore, just check for a non-zero return status, if this is too broad we can get more specific.
I think you reverted the check. It used to be "if blkid returns 2 overwrite the device" now you do "if blkid returns 0 we can overwrite the device".
Note: A user can still destroy her data if she enters the wrong password for a cryptsetup create. This we'll leave as the user's fault; she should be aware of the limitations of a plain mapping and the --verify-passphrase cryptsetup option. --- cryptmount.sh | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-)
diff --git a/cryptmount.sh b/cryptmount.sh index d602043..03699d0 100755 --- a/cryptmount.sh +++ b/cryptmount.sh @@ -1,6 +1,6 @@ #!/bin/sh
-SHORTOPTS="LMUc:w:nqvho:O:" +SHORTOPTS="LMUc:fw:nqvho:O:" DEPS="cryptsetup blkid findmnt mkswap mktemp" UDEVRUNNING=0
@@ -10,6 +10,7 @@ WAITTIME=10 CRYPTTAB=/etc/crypttab OPTIONS= FILTER="!noauto" +FORCE=0
ct_print_usage() { cat <<__EOF__ @@ -32,6 +33,8 @@ usage: $0 [OPTIONS] [-L]
options: -c FILE set the crypttab location (default: /etc/crypttab) + -f force destructive operations even when a block device appears to + contain data
As this is a bit dangerous stuff, it might be best to not have an -f option, but rather advice the user to use wipefs manually. Or are there situations where we really must force cryptsetup, but cannot run wipefs first?
-w NUM wait time (seconds) for a device if it is not already available -n dry run -q decrease verbosity @@ -115,6 +118,7 @@ ct_main() { M) set_action map;; U) set_action unmap;; c) CRYPTTAB="$OPTARG";; + f) FORCE=1;; w) WAITTIME=${OPTARG//[!0-9]};; n) DRYRUN=1;; q) LOGLEVEL=$(( LOGLEVEL - 1 ));; @@ -381,7 +385,14 @@ ct_map() {
info "device '$dev' assumed to be plain"
- if run cryptsetup create $key $args "$name" "$dev"; then + # cryptsetup 'create' can be destructive, don't do it if blkid can + # identify the device type + if [ $FORCE -ne 1 ] && blkid -p "$dev" &>/dev/null; then + error "Refusing to call 'cryptsetup create' on device that might" + error " have data. If you are sure this is what you want, use" + error " the -f option" + ret=1 + elif run cryptsetup create $key $args "$name" "$dev"; then info "sucessfully mapped '$dev' to '/dev/mapper/$name'" if [ $swap -eq 1 ]; then if run mkswap -f -L "$name" "/dev/mapper/$name"; then -- 1.7.10.2
On 05/18/2012 05:03 PM, Tom Gundersen wrote:
On Fri, May 18, 2012 at 6:22 PM, Matthew Monaco <dgbaley27@0x01b.net> wrote:
Currently in rc.sysinit we check that blkid returns 2 before running mkswap. This is a little bit stronger. Even without mkswap "cryptsetup create" can be dangerous, so do the blkid check for all plain (non-LUKS) mappings. Furthermore, just check for a non-zero return status, if this is too broad we can get more specific.
I think you reverted the check. It used to be "if blkid returns 2 overwrite the device" now you do "if blkid returns 0 we can overwrite the device".
I changed the check, but I don't think I reversed it. It's now: Iff blkid returns 0, we can't overwrite. Regardless, I think this was a bad decision on my part, blkid can error for some other reason and we don't want to allow an overwrite, I'll fix for checking '2' again.
Note: A user can still destroy her data if she enters the wrong password for a cryptsetup create. This we'll leave as the user's fault; she should be aware of the limitations of a plain mapping and the --verify-passphrase cryptsetup option. --- cryptmount.sh | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-)
diff --git a/cryptmount.sh b/cryptmount.sh index d602043..03699d0 100755 --- a/cryptmount.sh +++ b/cryptmount.sh @@ -1,6 +1,6 @@ #!/bin/sh
-SHORTOPTS="LMUc:w:nqvho:O:" +SHORTOPTS="LMUc:fw:nqvho:O:" DEPS="cryptsetup blkid findmnt mkswap mktemp" UDEVRUNNING=0
@@ -10,6 +10,7 @@ WAITTIME=10 CRYPTTAB=/etc/crypttab OPTIONS= FILTER="!noauto" +FORCE=0
ct_print_usage() { cat <<__EOF__ @@ -32,6 +33,8 @@ usage: $0 [OPTIONS] [-L]
options: -c FILE set the crypttab location (default: /etc/crypttab) + -f force destructive operations even when a block device appears to + contain data
As this is a bit dangerous stuff, it might be best to not have an -f option, but rather advice the user to use wipefs manually. Or are there situations where we really must force cryptsetup, but cannot run wipefs first?
No comment here, I just added -f as a convenience.
-w NUM wait time (seconds) for a device if it is not already available -n dry run -q decrease verbosity @@ -115,6 +118,7 @@ ct_main() { M) set_action map;; U) set_action unmap;; c) CRYPTTAB="$OPTARG";; + f) FORCE=1;; w) WAITTIME=${OPTARG//[!0-9]};; n) DRYRUN=1;; q) LOGLEVEL=$(( LOGLEVEL - 1 ));; @@ -381,7 +385,14 @@ ct_map() {
info "device '$dev' assumed to be plain"
- if run cryptsetup create $key $args "$name" "$dev"; then + # cryptsetup 'create' can be destructive, don't do it if blkid can + # identify the device type + if [ $FORCE -ne 1 ] && blkid -p "$dev" &>/dev/null; then + error "Refusing to call 'cryptsetup create' on device that might" + error " have data. If you are sure this is what you want, use" + error " the -f option" + ret=1 + elif run cryptsetup create $key $args "$name" "$dev"; then info "sucessfully mapped '$dev' to '/dev/mapper/$name'" if [ $swap -eq 1 ]; then if run mkswap -f -L "$name" "/dev/mapper/$name"; then -- 1.7.10.2
From: Matthew Monaco <matthew.monaco@0x01b.net> The key field may be device:key:fstype or device:key in which case the device is resolved and mounted if necessary. For these, key must be relative to the root of the filesystem on the device. The keydevice is mounted to $(mktemp -d). It is only unmounted if we mounted it. --- cryptmount.sh | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 74 insertions(+), 2 deletions(-) diff --git a/cryptmount.sh b/cryptmount.sh index 03699d0..a8a0ec8 100755 --- a/cryptmount.sh +++ b/cryptmount.sh @@ -341,8 +341,8 @@ ct_unmap() { ct_map() { -<<<<<<< HEAD local name="$1" dev="$2" key="$3" args="" swap=0 + local key_dev="" key_fstype="" key_mntpnt="" key_dev_umount=0 shift 3 if [ -e "/dev/mapper/$name" ]; then @@ -363,8 +363,71 @@ ct_map() { return 1 fi + # parse various key formats + case "$key" in + *:*:*) + key_dev="${key%%:*}" + key="${key#*:}" + key_fstype="${key%%:*}" + key="${key#*:}" + ;; + *:*) + key_dev="${key%%:*}" + key="${key#*:}" + ;; + ""|-) + unset key_dev + unset key + ;; + *) + unset key_dev + ;; + esac + + # resolve any needed key device and mount if necessary + if [ "$key_dev" ]; then + + if key_dev="$(ct_resolve_device "$key_dev")"; then + + if key_mntpnt="$(findmnt -cfmnoTARGET "$key_dev")"; then + + key="$key_mntpnt/$key" + + elif key_mntpnt="$(mktemp -d)"; then + + [ -n "$key_fstype" ] && key_fstype="-t $key_fstype" + + if run mount -r $key_fstype "$key_dev" "$key_mntpnt"; then + key="$key_mntpnt/$key" + key_dev_umount=1 + else + error "unable to mount key device '$key_dev'," + error " falling back on interactive password" + unset key + fi + else + error "unable to find or create mountpoint for key device," + error " falling back on interactive password" + unset key + fi + else + error "key device '$key_dev' not found" + error " falling back on interactive password" + unset key + fi + + elif [ -n "$key" -a "$key" != "-" ]; then + + if ! key="$(ct_resolve_device "$key")"; then + error "key '$key' not found" + error " falling back on interactive password" + unset key + fi + + fi + if [ "$key" ]; then - key="--key-file=\"$key\"" + key=--key-file="$key" fi local ret=0 @@ -409,6 +472,15 @@ ct_map() { fi + # clean up after ourselves + if [ $key_dev_umount -eq 1 ]; then + if ! run umount "$key_dev"; then + warn "unable to mount key device '$key_dev'" + else + run rmdir "$key_mntpnt" + fi + fi + return $ret } -- 1.7.10.2
On Fri, May 18, 2012 at 6:22 PM, Matthew Monaco <dgbaley27@0x01b.net> wrote:
From: Matthew Monaco <matthew.monaco@0x01b.net>
The key field may be device:key:fstype or device:key in which case the device is resolved and mounted if necessary. For these, key must be relative to the root of the filesystem on the device.
The keydevice is mounted to $(mktemp -d). It is only unmounted if we mounted it.
This mounts your device to /tmp/<something>. Are we sure that we never overmount something on /tmp between we mount and unmount the device? I guess it would be safer to create a folder under /run (e.g. /run/cryptmount) and use that as --tmpdir when using mktemp. Or maybe I'm overly paranoid...
cryptmount.sh | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 74 insertions(+), 2 deletions(-)
diff --git a/cryptmount.sh b/cryptmount.sh index 03699d0..a8a0ec8 100755 --- a/cryptmount.sh +++ b/cryptmount.sh @@ -341,8 +341,8 @@ ct_unmap() {
ct_map() {
-<<<<<<< HEAD local name="$1" dev="$2" key="$3" args="" swap=0 + local key_dev="" key_fstype="" key_mntpnt="" key_dev_umount=0 shift 3
if [ -e "/dev/mapper/$name" ]; then @@ -363,8 +363,71 @@ ct_map() { return 1 fi
+ # parse various key formats + case "$key" in + *:*:*) + key_dev="${key%%:*}" + key="${key#*:}" + key_fstype="${key%%:*}" + key="${key#*:}" + ;; + *:*) + key_dev="${key%%:*}" + key="${key#*:}" + ;; + ""|-) + unset key_dev + unset key + ;; + *) + unset key_dev + ;; + esac + + # resolve any needed key device and mount if necessary + if [ "$key_dev" ]; then + + if key_dev="$(ct_resolve_device "$key_dev")"; then + + if key_mntpnt="$(findmnt -cfmnoTARGET "$key_dev")"; then + + key="$key_mntpnt/$key" + + elif key_mntpnt="$(mktemp -d)"; then + + [ -n "$key_fstype" ] && key_fstype="-t $key_fstype" + + if run mount -r $key_fstype "$key_dev" "$key_mntpnt"; then + key="$key_mntpnt/$key" + key_dev_umount=1 + else + error "unable to mount key device '$key_dev'," + error " falling back on interactive password" + unset key + fi + else + error "unable to find or create mountpoint for key device," + error " falling back on interactive password" + unset key + fi + else + error "key device '$key_dev' not found" + error " falling back on interactive password" + unset key + fi + + elif [ -n "$key" -a "$key" != "-" ]; then + + if ! key="$(ct_resolve_device "$key")"; then + error "key '$key' not found" + error " falling back on interactive password" + unset key + fi + + fi + if [ "$key" ]; then - key="--key-file=\"$key\"" + key=--key-file="$key" fi
local ret=0 @@ -409,6 +472,15 @@ ct_map() {
fi
+ # clean up after ourselves + if [ $key_dev_umount -eq 1 ]; then + if ! run umount "$key_dev"; then + warn "unable to mount key device '$key_dev'" + else + run rmdir "$key_mntpnt" + fi + fi + return $ret }
-- 1.7.10.2
From: Matthew Monaco <matthew.monaco@0x01b.net> There are a few different syntaxes here. With no arguments, the ct_read_crypttab iterator is used. With 1 argument, a volume is found in crypttab. With 2-4 arguments, the volume is defined on the command line and crypttab is not used. --- cryptmount.sh | 44 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/cryptmount.sh b/cryptmount.sh index a8a0ec8..59c6c78 100755 --- a/cryptmount.sh +++ b/cryptmount.sh @@ -185,7 +185,13 @@ ct_main() { elif [ "$action" = "map" ]; then - : + if [ $# -ne 0 ]; then + [ "$FILTER" != "!noauto" ] && \ + info "Filters from -O are ignored in this mode" + unset FILTER + fi + + ct_main_map "$@" else @@ -214,6 +220,42 @@ ct_main_unmap() { fi } +ct_main_map() { + + if [ $# -eq 0 ]; then + + ct_read_crypttab ct_map + + elif [ $# -eq 1 ]; then + + local vol _tmp="$1" + + find_func() { + if [ "$1" = "$_tmp" -o "$2" = "$_tmp" ]; then + printf "%s" "$*" + else + false + fi + } + + if vol="$(ct_read_crypttab -1 find_func)"; then + ct_map $vol + else + error "Unable to find '$_tmp' in '$CRYPTTAB'" + false + fi + + elif [ $# -le 3 ]; then + + ct_map "$@" + + else + + error "Too many options given for -M" + ct_print_usage 1 + + fi +} # ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ # # # -- 1.7.10.2
From: Matthew Monaco <matthew.monaco@0x01b.net> --- cryptmount.sh | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/cryptmount.sh b/cryptmount.sh index 59c6c78..3844e01 100755 --- a/cryptmount.sh +++ b/cryptmount.sh @@ -302,6 +302,15 @@ ct_read_crypttab() { /dev/random|/dev/urandom) options="$options,%random" ;; + ASK) + info "$CRYPTTAB:$lineno: ASK is a deprecated key, please use '-' or 'none'" + key=- + ;; + SWAP) + info "$CRYPTTAB:$lineno: SWAP is a deprecated key, please use '/dev/urandom' and the 'swap' option" + key="/dev/urandom" + options="$options,swap,%random" + ;; /*|UUID=*|PARTUUID=*|LABEL=*) : ;; -- 1.7.10.2
The wording of these warnings might be a controversial, so just adding: Acked-by: Tom Gundersen <teg@jklm.no> to make sure some of the hate goes my way :-) On Fri, May 18, 2012 at 6:22 PM, Matthew Monaco <dgbaley27@0x01b.net> wrote:
From: Matthew Monaco <matthew.monaco@0x01b.net>
--- cryptmount.sh | 9 +++++++++ 1 file changed, 9 insertions(+)
diff --git a/cryptmount.sh b/cryptmount.sh index 59c6c78..3844e01 100755 --- a/cryptmount.sh +++ b/cryptmount.sh @@ -302,6 +302,15 @@ ct_read_crypttab() { /dev/random|/dev/urandom) options="$options,%random" ;; + ASK) + info "$CRYPTTAB:$lineno: ASK is a deprecated key, please use '-' or 'none'" + key=- + ;; + SWAP) + info "$CRYPTTAB:$lineno: SWAP is a deprecated key, please use '/dev/urandom' and the 'swap' option" + key="/dev/urandom" + options="$options,swap,%random" + ;; /*|UUID=*|PARTUUID=*|LABEL=*) : ;; -- 1.7.10.2
From: Matthew Monaco <matthew.monaco@0x01b.net> Give a deprecation notice though. --- cryptmount.sh | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/cryptmount.sh b/cryptmount.sh index 3844e01..37f5121 100755 --- a/cryptmount.sh +++ b/cryptmount.sh @@ -421,6 +421,18 @@ ct_map() { key="${key#*:}" key_fstype="${key%%:*}" key="${key#*:}" + case "$key_fstype" in + *[!0-9]*) + :;; + *) + warn "<dev>:<offset>:<length> is a deprecated key format. Please use" + warn " the keyfile-offset and keyfile-size options instead. This" + warn " format will *soon* be removed from cryptmount/crypttab!" + opts="$opts --keyfile-offset=$key_fstype --keyfile-size=$key" + key="$key_dev" + unset key_fstype + unset key_dev + esac ;; *:*) key_dev="${key%%:*}" -- 1.7.10.2
Ack. On Fri, May 18, 2012 at 6:22 PM, Matthew Monaco <dgbaley27@0x01b.net> wrote:
From: Matthew Monaco <matthew.monaco@0x01b.net>
Give a deprecation notice though. --- cryptmount.sh | 12 ++++++++++++ 1 file changed, 12 insertions(+)
diff --git a/cryptmount.sh b/cryptmount.sh index 3844e01..37f5121 100755 --- a/cryptmount.sh +++ b/cryptmount.sh @@ -421,6 +421,18 @@ ct_map() { key="${key#*:}" key_fstype="${key%%:*}" key="${key#*:}" + case "$key_fstype" in + *[!0-9]*) + :;; + *) + warn "<dev>:<offset>:<length> is a deprecated key format. Please use" + warn " the keyfile-offset and keyfile-size options instead. This" + warn " format will *soon* be removed from cryptmount/crypttab!" + opts="$opts --keyfile-offset=$key_fstype --keyfile-size=$key" + key="$key_dev" + unset key_fstype + unset key_dev + esac ;; *:*) key_dev="${key%%:*}" -- 1.7.10.2
From: Matthew Monaco <matthew.monaco@0x01b.net> It seems like some people use this. Use a new variable "tmpfs" to contain the file system type. Default to ext4 (Debian does this). Use the same variable to track the swap option too because we can only do one or the other. --- cryptmount.sh | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/cryptmount.sh b/cryptmount.sh index 37f5121..5320e3d 100755 --- a/cryptmount.sh +++ b/cryptmount.sh @@ -155,7 +155,7 @@ ct_main() { # Pre-parse OPTIONS, a little ugly, but it works preparse() { - local args swap + local args tmpfs if ! ct_parse_options $OPTIONS; then error "Invalid options string: $OPTIONS" exit 1 @@ -392,7 +392,7 @@ ct_unmap() { ct_map() { - local name="$1" dev="$2" key="$3" args="" swap=0 + local name="$1" dev="$2" key="$3" args="" tmpfs local key_dev="" key_fstype="" key_mntpnt="" key_dev_umount=0 shift 3 @@ -401,7 +401,7 @@ ct_map() { return 1 fi - # this function sets the args and swap variables + # this function sets the args and tmpfs variables if ! ct_parse_options "$@"; then error "Unable to parse options" return 1 @@ -520,13 +520,20 @@ ct_map() { ret=1 elif run cryptsetup create $key $args "$name" "$dev"; then info "sucessfully mapped '$dev' to '/dev/mapper/$name'" - if [ $swap -eq 1 ]; then + if [ "$tmpfs" = "swap" ]; then if run mkswap -f -L "$name" "/dev/mapper/$name"; then info "mkswap successful on '/dev/mapper/$name'" else error "mkswap failed for '/dev/mapper/$name'" ret=1 fi + elif [ "$tmpfs" ]; then + if run mkfs -t "$tmpfs" "/dev/mapper/$name"; then + info "mkfs successful on '/dev/mapper/$name'" + else + error "mkfs failed for '/dev/mapper/$name'" + ret=1 + fi fi else error "unable to map '$dev' to '/dev/maper/name/$name'" @@ -617,7 +624,7 @@ ct_parse_options() { case "$key" in swap) # set external variable - swap=1 + tmpfs="swap" ;; luks|plain) warn "Ignoring option $key, LUKS volumes are automatically detected" @@ -629,7 +636,9 @@ ct_parse_options() { warn "Ignoring Debian specific option '$key'" ;; tmp) - warn "The tmp= option is not supported" + # set an external variable + [ -z "$val" ] && msg "Defaulting tmp to ext4" + tmpfs="${val:-ext4}" ;; size) args="$args --key-size $val" -- 1.7.10.2
On Fri, May 18, 2012 at 6:22 PM, Matthew Monaco <dgbaley27@0x01b.net> wrote:
It seems like some people use this. Use a new variable "tmpfs" to contain the file system type. Default to ext4 (Debian does this). Use the same variable to track the swap option too because we can only do one or the other.
For the record: I don't see the value of this, and think people should use a real tmpfs backed by encrypted swap. That said, if there is demand for it I won't object. Does Debian support choosing your own filesystem or do they always use ext4? Having this be configurable seems a bit over the top to me...
--- cryptmount.sh | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-)
diff --git a/cryptmount.sh b/cryptmount.sh index 37f5121..5320e3d 100755 --- a/cryptmount.sh +++ b/cryptmount.sh @@ -155,7 +155,7 @@ ct_main() {
# Pre-parse OPTIONS, a little ugly, but it works preparse() { - local args swap + local args tmpfs if ! ct_parse_options $OPTIONS; then error "Invalid options string: $OPTIONS" exit 1 @@ -392,7 +392,7 @@ ct_unmap() {
ct_map() {
- local name="$1" dev="$2" key="$3" args="" swap=0 + local name="$1" dev="$2" key="$3" args="" tmpfs local key_dev="" key_fstype="" key_mntpnt="" key_dev_umount=0 shift 3
@@ -401,7 +401,7 @@ ct_map() { return 1 fi
- # this function sets the args and swap variables + # this function sets the args and tmpfs variables if ! ct_parse_options "$@"; then error "Unable to parse options" return 1 @@ -520,13 +520,20 @@ ct_map() { ret=1 elif run cryptsetup create $key $args "$name" "$dev"; then info "sucessfully mapped '$dev' to '/dev/mapper/$name'" - if [ $swap -eq 1 ]; then + if [ "$tmpfs" = "swap" ]; then if run mkswap -f -L "$name" "/dev/mapper/$name"; then info "mkswap successful on '/dev/mapper/$name'" else error "mkswap failed for '/dev/mapper/$name'" ret=1 fi + elif [ "$tmpfs" ]; then + if run mkfs -t "$tmpfs" "/dev/mapper/$name"; then + info "mkfs successful on '/dev/mapper/$name'" + else + error "mkfs failed for '/dev/mapper/$name'" + ret=1 + fi fi else error "unable to map '$dev' to '/dev/maper/name/$name'" @@ -617,7 +624,7 @@ ct_parse_options() { case "$key" in swap) # set external variable - swap=1 + tmpfs="swap" ;; luks|plain) warn "Ignoring option $key, LUKS volumes are automatically detected" @@ -629,7 +636,9 @@ ct_parse_options() { warn "Ignoring Debian specific option '$key'" ;; tmp) - warn "The tmp= option is not supported" + # set an external variable + [ -z "$val" ] && msg "Defaulting tmp to ext4" + tmpfs="${val:-ext4}" ;; size) args="$args --key-size $val" -- 1.7.10.2
On 05/18/2012 05:15 PM, Tom Gundersen wrote:
On Fri, May 18, 2012 at 6:22 PM, Matthew Monaco <dgbaley27@0x01b.net> wrote:
It seems like some people use this. Use a new variable "tmpfs" to contain the file system type. Default to ext4 (Debian does this). Use the same variable to track the swap option too because we can only do one or the other.
For the record: I don't see the value of this, and think people should use a real tmpfs backed by encrypted swap.
That said, if there is demand for it I won't object. Does Debian support choosing your own filesystem or do they always use ext4? Having this be configurable seems a bit over the top to me...
I implemented this exactly as debian does, "tmp" means ext4, but "tmp=<anything>" works too. I have no use for it, and wasn't even planning to add it, but I saw how simple it would be following the mkswap support (which I and others definitely do use).
--- cryptmount.sh | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-)
diff --git a/cryptmount.sh b/cryptmount.sh index 37f5121..5320e3d 100755 --- a/cryptmount.sh +++ b/cryptmount.sh @@ -155,7 +155,7 @@ ct_main() {
# Pre-parse OPTIONS, a little ugly, but it works preparse() { - local args swap + local args tmpfs if ! ct_parse_options $OPTIONS; then error "Invalid options string: $OPTIONS" exit 1 @@ -392,7 +392,7 @@ ct_unmap() {
ct_map() {
- local name="$1" dev="$2" key="$3" args="" swap=0 + local name="$1" dev="$2" key="$3" args="" tmpfs local key_dev="" key_fstype="" key_mntpnt="" key_dev_umount=0 shift 3
@@ -401,7 +401,7 @@ ct_map() { return 1 fi
- # this function sets the args and swap variables + # this function sets the args and tmpfs variables if ! ct_parse_options "$@"; then error "Unable to parse options" return 1 @@ -520,13 +520,20 @@ ct_map() { ret=1 elif run cryptsetup create $key $args "$name" "$dev"; then info "sucessfully mapped '$dev' to '/dev/mapper/$name'" - if [ $swap -eq 1 ]; then + if [ "$tmpfs" = "swap" ]; then if run mkswap -f -L "$name" "/dev/mapper/$name"; then info "mkswap successful on '/dev/mapper/$name'" else error "mkswap failed for '/dev/mapper/$name'" ret=1 fi + elif [ "$tmpfs" ]; then + if run mkfs -t "$tmpfs" "/dev/mapper/$name"; then + info "mkfs successful on '/dev/mapper/$name'" + else + error "mkfs failed for '/dev/mapper/$name'" + ret=1 + fi fi else error "unable to map '$dev' to '/dev/maper/name/$name'" @@ -617,7 +624,7 @@ ct_parse_options() { case "$key" in swap) # set external variable - swap=1 + tmpfs="swap" ;; luks|plain) warn "Ignoring option $key, LUKS volumes are automatically detected" @@ -629,7 +636,9 @@ ct_parse_options() { warn "Ignoring Debian specific option '$key'" ;; tmp) - warn "The tmp= option is not supported" + # set an external variable + [ -z "$val" ] && msg "Defaulting tmp to ext4" + tmpfs="${val:-ext4}" ;; size) args="$args --key-size $val" -- 1.7.10.2
From: Matthew Monaco <matthew.monaco@0x01b.net> This should support all of the current syntax. If that sentance is false, please let me know. This might be a good time to drop support for root=... without a cryptdevice=...? We'll support root, /usr, and anything tagged with %early in crypttab --- archlinux/encrypt_hook | 100 +++++++++++++++++++++++++++++++++++++++++++++ archlinux/encrypt_install | 56 +++++++++++++++++++++++++ 2 files changed, 156 insertions(+) create mode 100644 archlinux/encrypt_hook create mode 100644 archlinux/encrypt_install diff --git a/archlinux/encrypt_hook b/archlinux/encrypt_hook new file mode 100644 index 0000000..026c731 --- /dev/null +++ b/archlinux/encrypt_hook @@ -0,0 +1,100 @@ + +encrypt_main() { + + local tmp="$1" name="" dev="" key="${2:--}" opts="" log="" tab="${3:-/etc/crypttab}" + + case "$tmp" in + *:*:*) + dev="${tmp%%:*}" + tmp="${tmp#*:}" + name="${tmp%%:*}" + opts="${tmp#*:}" + ;; + *:*) + dev="${tmp%%:*}" + name="${tmp#*:}" + ;; + *) + name="$tmp" + ;; + esac + + if [ "$quiet" ]; then + log="-q" + elif [ "$verbose" ]; then + log="-v" + fi + + [ -e "/dev/mapper/$name" ] && return + + msg "Mapping encrypted volume '$name'" + + if [ "$dev" ]; then + cryptmount $log -O "$opts" -M "$name" "$dev" "$key" + else + cryptmount -c "$tab" $log -M "$name" + fi +} + +run_hook() { + + local vol vols + + if [ -z "$cryptdevice" ]; then + printf "The syntax 'root=%s' where '%s' is an encrypted volume is deprecated" \ + "Use 'cryptdevice=%s:root root=/dev/mapper/root instead." \ + "$root" "$root" "$root" + cryptdevice="$root:root" + root="/dev/mapper/root" + fi + + encrypt_main "$cryptdevice" "$cryptkey" +} + +run_latehook() { + + if [ "$cryptusr" ]; then + encrypt_main "$cryptusr" "$cryptusrkey" "/new_root/etc/crypttab" + fi + + if vols="$(cryptmount -c "/new_root/etc/fstab" -Lq -O "%early")" && [ "$vols" ]; then + for vol in $vols; do + [ -e "/dev/mapper/$vol" ] && continue + msg "Mapping encrypted volume '$vol'" + cryptmount -c "/new_root/etc/crypttab" -qM "$vol" + done + fi + + if [ -z "$cryptusr" ]; then + cryptusr="$(encrypt_from_mp "/usr")" || return + [ -e "/dev/mapper/$cryptusr" ] && return + msg "Detected /usr as '$cryptusr'" + encrypt_main "$cryptusr" + fi +} + +encrypt_from_mp() { + + local fstab="/new_root/etc/fstab" ctab="/new_root/etc/crypttab" + local line="" mp="$1" dev="" + + [ -f "$fstab" -a -r "$fstab" ] || return 1 + [ -f "$ctab" -a -r "$ctab" ] || return 1 + [ "$mp" ] || return 1 + + if ! dev="$(findmnt -sF "$fstab" -cfno SOURCE -T "$mp")"; then + return 1 + fi + + case "$dev" in + /dev/mapper/*) + printf "%s" "$(basename "$dev")" + return + ;; + *) + return 1 + ;; + esac +} + +# vim: set ft=sh ts=4 sw=4 noet : diff --git a/archlinux/encrypt_install b/archlinux/encrypt_install new file mode 100644 index 0000000..f0faf05 --- /dev/null +++ b/archlinux/encrypt_install @@ -0,0 +1,56 @@ +build() +{ + add_module dm-crypt + if [ $CRYPTO_MODULES ]; then + add_all_modules $CRYPTO_MODULES + else + add_all_modules "/crypto/" + fi + + add_runscript + + add_binary "cryptmount" + add_binary "cryptsetup" + add_binary "dmsetup" + add_binary "findmnt" + + add_file "/etc/crypttab" + + add_file "/usr/lib/udev/rules.d/10-dm.rules" + add_file "/usr/lib/udev/rules.d/13-dm-disk.rules" + add_file "/usr/lib/udev/rules.d/95-dm-notify.rules" + add_file "/usr/lib/initcpio/udev/11-dm-initramfs.rules" "/lib/udev/rules.d/11-dm-initramfs.rules" +} + +help() +{ +cat <<_EOF_ + This hook will _always_ attempt to map an encrypted root device. It will also + map an encrypted /usr device and attempt to automatically detect one if not + explicitly defined. Finally, it will map all devices in /etc/crypttab that have + the "%early" tag. (The %early tag is not necessary for root and /usr). + + The root device is defined with the 'cryptdevice' and 'cryptkey' options. If + they are defined as + + cryptdevice=<device>:<name>[:opt1,opt2,...] + cryptkey=<device>[[:<fstype>]:<path>] + + then no crypttab is needed and cryptkey has the exact same format and semantics + as the key field in crypttab(5). Otherwise, root may be defined as + + cryptdevice=<name> + + where <name> is used to find the volume definition in the crypttab ***which + was copied to your initrd during mkinitcpio(8)***. The cryptkey option is + ignored. + + For /usr, similar rules apply, using the 'cryptusr' and 'cryptkey' options. If + cryptusr is not defined, this hook will attempt to discover the correct volume + by looking in fstab (your /usr definition must be for /dev/mapper/<name> for + this to work). + +_EOF_ +} + +# vim: set ft=sh noet : -- 1.7.10.2
From: Matthew Monaco <matthew.monaco@0x01b.net> There are a couple of issues with the asciidoc. I'm also really tired right now so I'm sure there's plenty of awkward wording (this msg included). The format should be described almost completely in the manpage. The only thing I think I'm leaving out intentionally right now though is the support for dev:offset:length for the key field. The example file should include enough information to be useful, but little enough to be a good overview. And certainly not enough to be dangerous. --- crypttab.5.txt | 104 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ crypttab.example | 17 +++++++++ 2 files changed, 121 insertions(+) create mode 100644 crypttab.5.txt create mode 100644 crypttab.example diff --git a/crypttab.5.txt b/crypttab.5.txt new file mode 100644 index 0000000..8ce91a2 --- /dev/null +++ b/crypttab.5.txt @@ -0,0 +1,104 @@ +//// +vim:set ft=asciidoc noet tw=72: +//// +crypttab(5) +============= + +Name +---- +crypttab - static information about dm-crypt filesystems + +Synopsis +-------- +/etc/crypttab + +Description +----------- +The file *crypttab* contains information about encrypted volumes. +*crypttab* is intended to be read by *cryptmount*, and only written to +by human administrators. Each 'volume' is described on a separate line +by four fields. Fields are separated by whitespace. Empty lines and +lines beginning with a *#* are ignored. + +The fields are +'name' 'device' ['key' ['options']] + +'name':: + +The name of the 'volume' which will appear at +*/dev/mapper/*'name'. This must be a plain filename without any +directory components. + +'device':: + +An absolute path, UUID, PARTUUID, or LABEL to a device or file which +will be mapped to */dev/mapper/*'name'. + +'key' := *-* | 'keydevice'[\[*:*'fstype'] *:*'keyfile']:: + +This field may be blank or a *-* for interactive passwords. 'keydevice' +may be an absolute path, UUID, PARTUUID, or LABEL to a device or file +which contains the passphrase. If 'keyfile' (and 'fstype') are given, +'keydevice' will be mounted if it isn't already. 'keyfile' is an +absolute path relative to the root of the file system on 'keydevice'. ++ +For compatibility with other formats, *ASK* and *none* may be used in +place of *-* and *SWAP* is an idiom for */dev/urandom* and the *swap* +option. See *OPTIONS*. ++ +*Note:* A literal password in this field is *not* supported. + +'options' := 'key'[*=*'value'] | *%*'tag' | 'options'*,*'options':: + +The 'options' field is a comma separated list. It is described in detail +below. ++ +For compatibility with other formats, if the first character is *-* then +the entire field is interpretted as a literal command line for +*cryptsetup*. + +Options +------- + +Most options have a one-to-one correspondence to *cryptsetup* command +line options and are simply reformatted. For example to use *cryptsetup +--cipher/-c* 'cipher' the options *cipher*='cipher' or *c*='cipher' may +be used. Other options which are used by *cryptmount* are: + +*swap*:: + +Run *mkswap*(8) on */dev/mapper/*'name'. + +*tmp*[='fs']:: + +Run *mkfs*(8) with the file system type of 'fs' on */dev/mapper/*'name'. +The default 'fs' is *ext4*. + +*noauto*:: + +Do not automatically map this 'volume'. + +*size*='size':: + +See *cryptsetup(8) --key-size*. Other formats for *crypttab* use *size* +for the amount of bytes to read from *key*. + +*device-size*='size':: + +See *cryptsetup(8) --size*. This accounts for the quirk with *size*. + +*%*'tag':: + +Tags can be used to include or exclude a group of volumes when running +*cryptmount(8)*. Additionally, *cryptmount* automatically adds to +'volumes', with a key of */dev/urandom*, a *%random* tag. This tag is used +by the Arch Linux initscripts to delay the mapping of these volumes +until after the random seed has been restored during boot. + +See Also +-------- +*cryptmount*(8), *cryptsetup*(8) + +Authors +------- +Matt Monaco <dgbaley27@0x01b.net> diff --git a/crypttab.example b/crypttab.example new file mode 100644 index 0000000..80649db --- /dev/null +++ b/crypttab.example @@ -0,0 +1,17 @@ +# crypttab: mappings for encrypted volumes +# +# see crypttab(5) for the full details +# +# NAME - name of volume, /dev/mapper/NAME +# DEVICE - absolute path, UUID, PARTUUID, or LABEL of device or file +# KEY - -|<file>|<device>[[:fstype]:<file>] +# OPTIONS - options for cryptsetup, 'swap' runs mkswap after mapping, +# 'noauto' prevents automatic mapping + +#NAME DEVICE KEY OPTIONS +#root /dev/sda1 +#usr /dev/sda2 - allow-discards +#home /dev/sdb1 LABEL=usbdrv:/key +#swap /dev/sdb2 /dev/urandom swap,cipher=aes-cbc-essiv:sha256,size=128 +#data UUID=82d4f2... - noauto +#backup /home/backup LABEL=usbdrv2 noauto,keyfile-offset=500,keyfile-size=1024 -- 1.7.10.2
From: Matthew Monaco <matthew.monaco@0x01b.net> Ditto the last commit about awkward wording, even though I'm not quite as tired =) --- cryptmount.8.txt | 121 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 cryptmount.8.txt diff --git a/cryptmount.8.txt b/cryptmount.8.txt new file mode 100644 index 0000000..b5f06a9 --- /dev/null +++ b/cryptmount.8.txt @@ -0,0 +1,121 @@ +//// +vim:set ft=asciidoc noet tw=72: +//// +cryptmount(8) +============= + +Name +---- +cryptmount - parse *crypttab* for use by *cryptsetup* + +Synopsis +-------- +*cryptmount* ['options'] [*-L*] + +*cryptmount* ['options'] *-M* ['name'|'device'] + +*cryptmount* ['options'] *-M* 'name' 'device' ['key'] + +*cryptmount* ['options'] *-U* ['name'[*,*...]] + +Description +----------- + +*cryptmount* uses *crypttab(5)* for calling *cryptsetup(8)*; it can also +be used to define a 'volume' on the command line without *crypttab*. + +Actions +------- + +*-L*:: + +List the 'names' (first column) of 'volumes' from *crypttab*. Use with +*-O* to manipulate which 'names' are listed. + +*-M*:: + +Perform a mapping. The first form of this command finds a 'volume' from +*crypttab* either by its 'name' or 'device', or if nothing is given then +map all 'volumes' (use with *-O* to manipulate which 'volumes' are +mapped). The second form defines a 'volume' entirely on the command +line, *crypttab* is not used. + +*-U*:: + +Unmap 'volume(s)'. If a list of 'names' is given, unmap them. Otherwise +unmap all 'volumes' from *crypttab* (with *-O* to manipulate which +'volumes' are unmapped). + +Options +------- + +*-c* 'file':: + +Override the default *crypttab* location. + +*-f*:: + +Force potentially destructive mappings. For plain mappings (which are +used with the *swap* and *tmp* options), there is a lot of potential to +accidentally lose data. Because of this, *cryptmount* performs a check +with *blkid(8)* to see if there is anything identifiable on 'device'. +Use *-f* to bypass this check. + +*-w* 'num':: + +Time (in seconds) to wait for 'device' if it is not already available. +If *udevd(8)* is not running, then *cryptmount* does not bother to wait +and this option is a no-op. This also affects the wait time for +'keydevice' if your key is a block device or a file on a block device. + +*-n*:: + +Dry run, useful with *-v* to see how *cryptsetup* will be called. + +*-v*:: + +Increase verbosity. This prints the commands which are being called (eg: +*cryptsetup*, *mkswap*). + +*-q*:: + +Decrease verbosity. + +*-h*:: + +Print a short usage message and exit. + +*-o* 'options':: + +An options list with items such as *swap*, *cipher*, etc. This may be +given multiple times with a cumulative effect. See *crypttab(5)* for the +full syntax 'options'. + +*-O* 'filters':: + +Similar to 'options', this is used to manipulate which 'volumes' are +used with '-L' and with '-M'/'-U' without arguments. If an option is +present in 'filters', then the 'volume' in *crypttab* must contain the +option. For example *-O swap,size* matches all 'volumes' with the *swap* +option *and* any *size=*'size' option; or *-O swap,size=512* matches +only those 'volumes' with the *swap* option and specifically *size=512*. ++ +A filter option may also be negated by prefixing it with a *!*. For +example, *-O swap,!size* includes all 'volumes' with the *swap* option +but *without* the 'size' option. There is a built-in filter *!noauto*. ++ +Filters are especially useful with *%*'tag' options. For example, *-O +!%random* can be used to map all 'volumes' which don't use +*/dev/urandom* for a password and *-O %random* to map the remainder once +your system's random seed has been restored. ++ +The *-O* option has *no effect* when calling *cryptmount* in a way that +does not use *crypttab*. + +See Also +-------- +*crypttab*(5), *cryptsetup*(8) + +Authors +------- +Matt Monaco <dgbaley27@0x01b.net> -- 1.7.10.2
From: Matthew Monaco <matthew.monaco@0x01b.net> This might be more than it needs to be. I anticipate systemd deciding to provide a crypttab man page at some point so I wanted to be someone flexible here. --- .gitignore | 5 +++++ Makefile | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) create mode 100644 Makefile diff --git a/.gitignore b/.gitignore index 7cd538a..203f504 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,8 @@ # Editor Files .*.swp *~ + +# Build Files +cryptmount +*.8 +*.5 diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..b73df91 --- /dev/null +++ b/Makefile @@ -0,0 +1,50 @@ +BIN ?= cryptmount +MANPAGES := crypttab.5 cryptmount.8 + +PREFIX ?= /usr/local +BINDIR ?= $(PREFIX)/bin +LIBDIR ?= $(PREFIX)/lib +DATADIR ?= $(PREFIX)/share +MANDIR ?= $(DATADIR)/man + +DOCDIRS := $(addprefix $(DESTDIR)$(MANDIR)/man, 5 8) $(DESTDIR)$(DATADIR)/$(BIN) +HOOKDIRS := $(addprefix $(DESTDIR)$(LIBDIR)/initcpio/, install hooks) + + +all: $(BIN) $(MANPAGES) + + +$(BIN): $(BIN).sh + cp $< $@ + +man: $(MANPAGES) + +%.5: %.5.txt + a2x -d manpage -f manpage $< + +%.8: %.8.txt + a2x -d manpage -f manpage $< + + +install: install_bin install_doc + +install_bin: $(BIN) $(DESTDIR)$(BINDIR) + install -m755 -t $(DESTDIR)$(BINDIR) $(BIN) + +install_doc: $(MANPAGES) crypttab.example $(DOCDIRS) + install -m644 -t $(DESTDIR)$(MANDIR)/man5 $(filter %.5, $(MANPAGES)) + install -m644 -t $(DESTDIR)$(MANDIR)/man8 $(filter %.8, $(MANPAGES)) + install -m644 -t $(DESTDIR)$(DATADIR)/$(BIN) crypttab.example + +install_hook: archlinux/encrypt_hook archlinux/encrypt_install $(HOOKDIRS) + install -m644 archlinux/encrypt_install $(DESTDIR)$(LIBDIR)/initcpio/install/encrypt2 + install -m644 archlinux/encrypt_hook $(DESTDIR)$(LIBDIR)/initcpio/hooks/encrypt2 + +$(DESTDIR)$(BINDIR) $(HOOKDIRS) $(DOCDIRS): + install -m755 -d $@ + + +clean: + $(RM) $(BIN) $(MANPAGES) + +.PHONY: all man clean install install_bin install_doc install_hook -- 1.7.10.2
From: Matthew Monaco <matthew.monaco@0x01b.net> --- .gitignore | 5 +++++ archlinux/PKGBUILD | 25 +++++++++++++++++++++++++ 2 files changed, 30 insertions(+) create mode 100644 archlinux/PKGBUILD diff --git a/.gitignore b/.gitignore index 203f504..bb4def3 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,8 @@ cryptmount *.8 *.5 + +# Arch Linux Files +archlinux/src +archlinux/pkg +archlinux/*.tar.* diff --git a/archlinux/PKGBUILD b/archlinux/PKGBUILD new file mode 100644 index 0000000..158dc49 --- /dev/null +++ b/archlinux/PKGBUILD @@ -0,0 +1,25 @@ + +pkgname=cryptmount +pkgver=$(date +%Y%m%d) +pkgrel=1 +pkgdesc="Standardized crypttab handler for cryptsetup" +arch=('any') +url="https://github.com/mmonaco/cryptmount" +license=('GPL') +depends=('cryptsetup') +makedepends=('asciidoc') + +source=() +md5sums=() + +build() { + cd "$startdir" + make -C ../ all +} + +package() { + cd "$startdir" + make -C ../ DESTDIR="$pkgdir" PREFIX="/usr" install install_hook +} + +# vim: set noet : -- 1.7.10.2
From: Matthew Monaco <matthew.monaco@0x01b.net> Cryptmount provides a lot of the work that is duplicate in the mkinitcpio encrypt hook and initscripts. Use it to map all volumes from crypttab that don't have "noauto" and which aren't already mounted. Also, use it to unmap volumes in crypttab that aren't already mounted and aren't / or /usr. --- PKGBUILD | 2 +- functions | 94 ----------------------------------------------------------- rc.shutdown | 53 +++++++++++++++++++++++---------- rc.sysinit | 37 ++++++++++++++++++----- 4 files changed, 68 insertions(+), 118 deletions(-) diff --git a/PKGBUILD b/PKGBUILD index 3130e5e..36c85b0 100644 --- a/PKGBUILD +++ b/PKGBUILD @@ -10,7 +10,7 @@ conflicts=('initscripts') provides=('initscripts=9999') backup=(etc/inittab etc/rc.conf etc/rc.local etc/rc.local.shutdown) makedepends=('asciidoc') -depends=('glibc' 'bash' 'grep' 'coreutils' 'udev>=182' 'iproute2' +depends=('glibc' 'bash' 'grep' 'coreutils' 'cryptmount' 'udev>=182' 'iproute2' 'ncurses' 'kbd' 'findutils' 'sysvinit') optdepends=('net-tools: legacy networking support' 'bridge-utils: Network bridging support' diff --git a/functions b/functions index 7516345..fd20349 100644 --- a/functions +++ b/functions @@ -377,100 +377,6 @@ activate_vgs() { (( $? == 0 )) && stat_done || stat_fail } -do_unlock() { - # $1 = requested name - # $2 = source device - # $3 = password - # $4 = options - stat_append "${1}.." - local open=create a=$1 b=$2 failed=0 - # Ordering of options is different if you are using LUKS vs. not. - # Use ugly swizzling to deal with it. - # isLuks only gives an exit code but no output to stdout or stderr. - if cryptsetup isLuks "$2" 2>/dev/null; then - open=luksOpen - a=$2 - b=$1 - fi - case $3 in - SWAP) - local _overwriteokay=0 - if [[ -b $2 && -r $2 ]]; then - # This is DANGEROUS! If there is any known file system, - # partition table, RAID or LVM volume on the device - # we don't overwrite it. - # - # 'blkid' returns 2 if no valid signature has been found. - # Only in this case we should allow overwriting the device. - # - # This sanity check _should_ be sufficient, but it might not. - # This may cause dataloss if it is not used carefully. - blkid -p "$2" &>/dev/null - (( $? == 2 )) && _overwriteokay=1 - fi - if (( _overwriteokay == 0 )); then - false - elif cryptsetup -d /dev/urandom $4 $open "$a" "$b" >/dev/null; then - stat_append "creating swapspace.." - mkswap -f -L $1 /dev/mapper/$1 >/dev/null - fi;; - ASK) - printf "\nOpening '$1' volume:\n" - cryptsetup $4 $open "$a" "$b" < /dev/console;; - /dev*) - local ckdev=${3%%:*} - local cka=${3#*:} - local ckb=${cka#*:} - local cka=${cka%:*} - local ckfile=/dev/ckfile - local ckdir=/dev/ckdir - case ${cka} in - *[!0-9]*) - # Use a file on the device - # cka is not numeric: cka=filesystem, ckb=path - mkdir ${ckdir} - mount -r -t ${cka} ${ckdev} ${ckdir} - dd if=${ckdir}/${ckb} of=${ckfile} >/dev/null 2>&1 - umount ${ckdir} - rmdir ${ckdir};; - *) - # Read raw data from the block device - # cka is numeric: cka=offset, ckb=length - dd if=${ckdev} of=${ckfile} bs=1 skip=${cka} count=${ckb} >/dev/null 2>&1;; - esac - cryptsetup -d ${ckfile} $4 $open "$a" "$b" >/dev/null - dd if=/dev/urandom of=${ckfile} bs=1 count=$(stat -c %s ${ckfile}) conv=notrunc >/dev/null 2>&1 - rm ${ckfile};; - /*) - cryptsetup -d "$3" $4 $open "$a" "$b" >/dev/null;; - *) - printf "${C_FAIL}crypttab contains a literal encryption key. This will stop working in the future.${C_OTHER}\n" - echo "$3" | cryptsetup $4 $open "$a" "$b" >/dev/null;; - esac - if (( $? )); then - failed=1 - stat_append "failed " - else - stat_append "ok " - fi - return $failed -} - -read_crypttab() { - # $1 = function to call with the split out line from the crypttab - local line nspo failed=0 - while read line; do - [[ $line && $line != '#'* ]] || continue - eval nspo=("${line%#*}") - if $1 "${nspo[0]}" "${nspo[1]}" "${nspo[2]}" "${nspo[*]:3}"; then - crypto_unlocked=1 - else - failed=1 - fi - done < /etc/crypttab - return $failed -} - set_timezone() { local tz=$1 zonefile=/usr/share/zoneinfo/$1 diff --git a/rc.shutdown b/rc.shutdown index ec30d56..292de7e 100755 --- a/rc.shutdown +++ b/rc.shutdown @@ -64,23 +64,44 @@ status "Unmounting Non-API Filesystems" umount_all run_hook shutdown_postumount -# Kill non-root encrypted partition mappings -if [[ -f /etc/crypttab ]] && type -p cryptsetup >/dev/null; then +deactivate_cryptos() { + local vol vols mntpnt fail=0 i=0 + + [[ -f "/etc/crypttab" ]] || return + type -p cryptmount >/dev/null || return + mapfile -t vols < <(cryptmount -Lq "$@") + + for ((i = 0; i < ${#vols[@]}; i++)); do + if [[ ! -e "/dev/mapper/${vols[$i]}" ]]; then + unset vols[$i] + elif mntpnt="$(findmnt -S "/dev/mapper/${vols[$i]}" -noTARGET)" && \ + [[ "$mntpnt" = "/" || "$mntpnt" = "/usr" ]]; then + unset vols[$i] + fi + done + + (( ${#vols[@]} )) || return + stat_busy "Deactivating encrypted volumes:" - # Maybe someone has LVM on an encrypted block device - # executing an extra vgchange is errorless - [[ $USELVM = [Yy][Ee][Ss] ]] && vgchange --sysinit -a n &>/dev/null - do_lock() { - stat_append "${1}.." - if cryptsetup remove "$1" &>/dev/null; then - stat_append "ok " - else - stat_append "failed " - fi - } - read_crypttab do_lock - stat_done -fi + + # Maybe someone has LVM on an encrypted block device + # executing an extra vgchange is errorless + [[ $USELVM = [Yy][Ee][Ss] ]] && vgchange --sysinit -a n &>/dev/null + + for vol in ${vols[@]}; do + if cryptmount -Uq "$vol"; then + stat_append "$C_DONE $vol$C_MAIN" + else + stat_append "$C_FAIL $vol$C_MAIN" + fail=1 + fi + done + + (( fail )) && stat_fail || stat_done +} + +# Kill any mapped volumes in crypttab (exclude / and /usr) +deactivate_cryptos [[ $USELVM = [Yy][Ee][Ss] && -x $(type -P lvm) && -d /sys/block ]] && status "Deactivating LVM2 groups" vgchange --sysinit -a n &>/dev/null diff --git a/rc.sysinit b/rc.sysinit index f91190c..c2de464 100755 --- a/rc.sysinit +++ b/rc.sysinit @@ -123,14 +123,37 @@ udevd_modprobe sysinit # Activate LVM2 groups if any activate_vgs -# Set up non-root encrypted partition mappings -if [[ -f /etc/crypttab ]] && type -p cryptsetup >/dev/null; then +activate_cryptos() { + local vol vols fail=0 unlocked=0 i=0 + + [[ -f "/etc/crypttab" ]] || return + type -p cryptmount >/dev/null || return + mapfile -t vols < <(cryptmount -Lq "$@") + + for ((i = 0; i < ${#vols[@]}; i++)); do + [[ ! -e "/dev/mapper/${vols[$i]}" ]] || unset vols[$i] + done + + (( ${#vols[@]} )) || return + stat_busy "Unlocking encrypted volumes:" - crypto_unlocked=0 - read_crypttab do_unlock && stat_done || stat_fail - # Maybe someone has LVM on an encrypted block device - (( crypto_unlocked )) && activate_vgs -fi + + for vol in ${vols[@]}; do + if cryptmount -Mq "$vol"; then + stat_append "$C_DONE $vol$C_MAIN" + unlocked=1 + else + stat_append "$C_FAIL $vol$C_MAIN" + fail=1 + fi + done + + (( fail )) && stat_fail || stat_done + (( unlocked )) && activate_vgs +} + +# Map any unmapped encrypted volumes in crypttab +activate_cryptos # Check filesystems run_hook sysinit_prefsck -- 1.7.10.2
From: Matthew Monaco <matthew.monaco@0x01b.net> The differences compared to the existing inline implementation are: - can use cat again for loading - the calculated pool size can be local - quote file names... can't hurt --- functions | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/functions b/functions index fd20349..b1dd5c1 100644 --- a/functions +++ b/functions @@ -506,6 +506,27 @@ bootlogd_stop() { -e 's/\^\[(\[1?[0-9][0-9]|%)G//g' -e 's/\^\[\[0;1//g' /var/log/boot } +RANDOM_SEED=/var/lib/misc/random-seed +RANDOM_POOL_FILE=/proc/sys/kernel/random/poolsize + +load_random_seed() { + if [[ -f "$RANDOM_SEED" ]]; then + cat "$RANDOM_SEED" > /dev/urandom + fi +} + +store_random_seed() { + local pool_size + install -TDm 0600 /dev/null "$RANDOM_SEED" + if [[ -r "$RANDOM_POOL_FILE" ]]; then + read pool_size < "$RANDOM_POOL_FILE" + (( pool_size /= 8 )) + else + pool_size=512 + fi + dd if=/dev/urandom of="$RANDOM_SEED" count=1 bs=$pool_size &> /dev/null +} + ############################### # Custom hooks in initscripts # ############################### -- 1.7.10.2
On Fri, May 18, 2012 at 6:22 PM, Matthew Monaco <dgbaley27@0x01b.net> wrote:
From: Matthew Monaco <matthew.monaco@0x01b.net>
The differences compared to the existing inline implementation are:
- can use cat again for loading - the calculated pool size can be local - quote file names... can't hurt
Looks good. We might end up moving to the systemd implementation of these things if Dave packages "systemd-tools" or something like that, but I'm happy to take this for the time being.
--- functions | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+)
diff --git a/functions b/functions index fd20349..b1dd5c1 100644 --- a/functions +++ b/functions @@ -506,6 +506,27 @@ bootlogd_stop() { -e 's/\^\[(\[1?[0-9][0-9]|%)G//g' -e 's/\^\[\[0;1//g' /var/log/boot }
+RANDOM_SEED=/var/lib/misc/random-seed +RANDOM_POOL_FILE=/proc/sys/kernel/random/poolsize + +load_random_seed() { + if [[ -f "$RANDOM_SEED" ]]; then + cat "$RANDOM_SEED" > /dev/urandom + fi +} + +store_random_seed() { + local pool_size + install -TDm 0600 /dev/null "$RANDOM_SEED" + if [[ -r "$RANDOM_POOL_FILE" ]]; then + read pool_size < "$RANDOM_POOL_FILE" + (( pool_size /= 8 )) + else + pool_size=512 + fi + dd if=/dev/urandom of="$RANDOM_SEED" count=1 bs=$pool_size &> /dev/null +} + ############################### # Custom hooks in initscripts # ############################### -- 1.7.10.2
From: Matthew Monaco <matthew.monaco@0x01b.net> --- rc.shutdown | 13 +------------ rc.sysinit | 5 +---- 2 files changed, 2 insertions(+), 16 deletions(-) diff --git a/rc.shutdown b/rc.shutdown index 292de7e..7498fb0 100755 --- a/rc.shutdown +++ b/rc.shutdown @@ -19,18 +19,7 @@ run_hook shutdown_start stop_all_daemons -stat_busy "Saving Random Seed" - RANDOM_SEED=/var/lib/misc/random-seed - install -TDm 0600 /dev/null $RANDOM_SEED - POOL_FILE=/proc/sys/kernel/random/poolsize - if [[ -r $POOL_FILE ]]; then - read POOL_SIZE < $POOL_FILE - (( POOL_SIZE /= 8 )) - else - POOL_SIZE=512 - fi - dd if=/dev/urandom of=$RANDOM_SEED count=1 bs=$POOL_SIZE &>/dev/null -stat_done +status "Saving Random Seed" store_random_seed [[ $TIMEZONE ]] && status "Configuring Time Zone" set_timezone "$TIMEZONE" diff --git a/rc.sysinit b/rc.sysinit index c2de464..04ee0fb 100755 --- a/rc.sysinit +++ b/rc.sysinit @@ -188,10 +188,7 @@ status "Activating Swap" swapon -a [[ $TIMEZONE ]] && status "Configuring Time Zone" set_timezone "$TIMEZONE" -RANDOM_SEED=/var/lib/misc/random-seed -[[ -f $RANDOM_SEED ]] && - status "Initializing Random Seed" \ - cp $RANDOM_SEED /dev/urandom +status "Initializing Random Seed" load_random_seed # Remove leftover files remove_leftover -- 1.7.10.2
From: Matthew Monaco <matthew.monaco@0x01b.net> This will prevent the system from booting with a previous seed in the event that rc.shutdown is not run cleanly. --- rc.sysinit | 1 + 1 file changed, 1 insertion(+) diff --git a/rc.sysinit b/rc.sysinit index 04ee0fb..b95defc 100755 --- a/rc.sysinit +++ b/rc.sysinit @@ -189,6 +189,7 @@ status "Activating Swap" swapon -a [[ $TIMEZONE ]] && status "Configuring Time Zone" set_timezone "$TIMEZONE" status "Initializing Random Seed" load_random_seed +status "Storing new Random Seed" store_random_seed # Remove leftover files remove_leftover -- 1.7.10.2
From: Matthew Monaco <matthew.monaco@0x01b.net> For encryped volumes with a random passphrase -- typically those used for swap space -- it's desireable to set up AFTER the random seed has been restored. Unfortunately, in many situations the random seed is stored on another encrypted volume. To solve this only map non-random volumes in the current location. Later on, map the random volumes after the random seed has been loaded. This also involves moving swapon down a few lines. --- rc.sysinit | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/rc.sysinit b/rc.sysinit index b95defc..270f384 100755 --- a/rc.sysinit +++ b/rc.sysinit @@ -152,8 +152,8 @@ activate_cryptos() { (( unlocked )) && activate_vgs } -# Map any unmapped encrypted volumes in crypttab -activate_cryptos +# Map any unmapped encrypted volumes in crypttab, non-random +activate_cryptos -O \!%random # Check filesystems run_hook sysinit_prefsck @@ -184,13 +184,16 @@ run_hook sysinit_postmount status "Activating monitoring of LVM2 groups" \ vgchange --monitor y >/dev/null -status "Activating Swap" swapon -a - [[ $TIMEZONE ]] && status "Configuring Time Zone" set_timezone "$TIMEZONE" status "Initializing Random Seed" load_random_seed status "Storing new Random Seed" store_random_seed +# Map any unmapped encrypted volumes in crypttab, only random +activate_cryptos -O %random + +status "Activating Swap" swapon -a + # Remove leftover files remove_leftover -- 1.7.10.2
From: Matthew Monaco <matthew.monaco@0x01b.net> We'll have the late hook in the initrd automatically map all volumes with an %early tag. Skipping them here is up for discussion though, as they should be skipped if they're mapped anyway. What should the procedure be if we're in rc.sysinit, and an %early volume is not mounted for whatever reason? --- rc.sysinit | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rc.sysinit b/rc.sysinit index 270f384..be51dbb 100755 --- a/rc.sysinit +++ b/rc.sysinit @@ -153,7 +153,7 @@ activate_cryptos() { } # Map any unmapped encrypted volumes in crypttab, non-random -activate_cryptos -O \!%random +activate_cryptos -O '!%early,!%random' # Check filesystems run_hook sysinit_prefsck @@ -190,7 +190,7 @@ status "Initializing Random Seed" load_random_seed status "Storing new Random Seed" store_random_seed # Map any unmapped encrypted volumes in crypttab, only random -activate_cryptos -O %random +activate_cryptos -O '!%early,%random' status "Activating Swap" swapon -a -- 1.7.10.2
On Fri, May 18, 2012 at 6:22 PM, Matthew Monaco <dgbaley27@0x01b.net> wrote:
From: Matthew Monaco <matthew.monaco@0x01b.net>
We'll have the late hook in the initrd automatically map all volumes with an %early tag. Skipping them here is up for discussion though, as they should be skipped if they're mapped anyway.
I don't like this patch. Actually, not sure if I like the %early tag in the first place (is this the syntax other distro's use as well?). I don't think there is any need for marking things as %early, the only time the initrd might read the real crypttab is after the rootfs has been mounted, and then it's only job is to set up whatever is needed to mount /usr. Or am I missing some setup we want to support where the initrd can not figure out which volumes to map? Notice that encrypting /usr is almost entirely pointless, so we should be very hesitant to add syntax just to support this.
What should the procedure be if we're in rc.sysinit, and an %early volume is not mounted for whatever reason?
Then we should set it up.
rc.sysinit | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/rc.sysinit b/rc.sysinit index 270f384..be51dbb 100755 --- a/rc.sysinit +++ b/rc.sysinit @@ -153,7 +153,7 @@ activate_cryptos() { }
# Map any unmapped encrypted volumes in crypttab, non-random -activate_cryptos -O \!%random +activate_cryptos -O '!%early,!%random'
# Check filesystems run_hook sysinit_prefsck @@ -190,7 +190,7 @@ status "Initializing Random Seed" load_random_seed status "Storing new Random Seed" store_random_seed
# Map any unmapped encrypted volumes in crypttab, only random -activate_cryptos -O %random +activate_cryptos -O '!%early,%random'
status "Activating Swap" swapon -a
-- 1.7.10.2
On 05/18/2012 05:50 PM, Tom Gundersen wrote:
On Fri, May 18, 2012 at 6:22 PM, Matthew Monaco <dgbaley27@0x01b.net> wrote:
From: Matthew Monaco <matthew.monaco@0x01b.net>
We'll have the late hook in the initrd automatically map all volumes with an %early tag. Skipping them here is up for discussion though, as they should be skipped if they're mapped anyway.
I don't like this patch.
Actually, not sure if I like the %early tag in the first place (is this the syntax other distro's use as well?). I don't think there is any need for marking things as %early, the only time the initrd might read the real crypttab is after the rootfs has been mounted, and then it's only job is to set up whatever is needed to mount /usr. Or am I missing some setup we want to support where the initrd can not figure out which volumes to map? Notice that encrypting /usr is almost entirely pointless, so we should be very hesitant to add syntax just to support this.
I did this in response for two feature requests asking for more flexibility in the initrd. Without much code the %early tag allows for an arbitrary number of mounts. Others are not using tags like this, but sysd ignores unknown options so it should be safe.
On Sat, May 19, 2012 at 1:56 AM, Matthew Monaco <dgbaley27@0x01b.net> wrote:
I did this in response for two feature requests asking for more flexibility in the initrd. Without much code the %early tag allows for an arbitrary number of mounts. Others are not using tags like this, but sysd ignores unknown options so it should be safe.
I'm hesitant to add new syntax without good usecases (as we have to support it for a long time). I think the correct way to do this is to map encrypted devices on-demand, but that doesn't really fit with the way we do things. I guess it would be ok to add the %early tags for now, and if people in the future add systemd to the initrd this stuff wolud "just work" with or without the %early tag, so it does not really matter what we do. -t
On 05/18/2012 06:28 PM, Tom Gundersen wrote:
On Sat, May 19, 2012 at 1:56 AM, Matthew Monaco <dgbaley27@0x01b.net> wrote:
I did this in response for two feature requests asking for more flexibility in the initrd. Without much code the %early tag allows for an arbitrary number of mounts. Others are not using tags like this, but sysd ignores unknown options so it should be safe.
I'm hesitant to add new syntax without good usecases (as we have to support it for a long time). I think the correct way to do this is to map encrypted devices on-demand, but that doesn't really fit with the way we do things.
I guess it would be ok to add the %early tags for now, and if people in the future add systemd to the initrd this stuff wolud "just work" with or without the %early tag, so it does not really matter what we do.
-t
Don't forget, this is just an extension of my solution for random key devices. So if you don't like it we need to rethink it there. This was just a simple extension of that solution.
participants (2)
-
Matthew Monaco
-
Tom Gundersen