* [PATCH 1/2] 99base/dracut-lib.sh: 7 new functions & 1 modified
@ 2010-10-03 22:44 Amadeusz Żołnowski
[not found] ` <1286145886-16322-1-git-send-email-aidecoe-2qtfh70TtYba5EbDDlwbIw@public.gmane.org>
0 siblings, 1 reply; 6+ messages in thread
From: Amadeusz Żołnowski @ 2010-10-03 22:44 UTC (permalink / raw)
To: initramfs-u79uwXL29TY76Z2rM5mHXA
str_starts, str_replace
chr - decimal value to character
funiq - print new unique file name
mkuniqdir - create and print new unique dir
enc_nonprn_white - encode non-printable and white chars to '\xHH'
foreach_dev_until - evaluates command for every given device
modified:
foreach_uuid_until - use $___ as a place holder
---
modules.d/99base/dracut-lib.sh | 142 ++++++++++++++++++++++++++++++++++++++--
1 files changed, 135 insertions(+), 7 deletions(-)
diff --git a/modules.d/99base/dracut-lib.sh b/modules.d/99base/dracut-lib.sh
index 627d2c5..e8a7850 100755
--- a/modules.d/99base/dracut-lib.sh
+++ b/modules.d/99base/dracut-lib.sh
@@ -6,6 +6,35 @@ strstr() {
[ "${1#*$2*}" != "$1" ]
}
+# returns OK if $1 contains $2 at the beginning
+str_starts() {
+ [ "${1#$2*}" != "$1" ]
+}
+
+# converts decimal value to its ASCII character representation
+# <http://mywiki.wooledge.org/BashFAQ/071>
+chr() {
+ printf \\$(($1/64*100+$1%64/8*10+$1%8))
+}
+
+# replaces all occurrences of 'search' in 'str' with 'replacement'
+#
+# str_replace str search replacement
+#
+# example:
+# str_replace ' one two three ' ' ' '_'
+str_replace() {
+ local in="$1"; local s="$2"; local r="$3"
+ local out=''
+
+ while strstr "${in}" "$s"; do
+ chop="${in%%$s*}"
+ out="${out}${chop# }$r"
+ in="${in#*$s}"
+ done
+ echo "${out}${in}"
+}
+
getarg() {
set +x
local o line val
@@ -283,35 +312,134 @@ ip_to_var() {
esac
}
-# Evaluate command for UUIDs either given as arguments for this function or all
+# Prints unique path for potential file inside specified directory. It consists
+# of specified directory, prefix and number at the end which is incremented
+# until non-existing file is found.
+#
+# funiq dir prefix
+#
+# example:
+# # ls /mnt
+# cdrom0 cdrom1
+#
+# # funiq /mnt cdrom
+# /mnt/cdrom2
+funiq() {
+ local dir="$1"; local prefix="$2"
+ local i=0
+
+ [ -d "${dir}" ] || return 1
+
+ while [ -e "${dir}/${prefix}$i" ]; do
+ i=$(($i+1)) || return 1
+ done
+
+ echo "${dir}/${prefix}$i"
+}
+
+# Creates unique directory and prints its path. It's using funiq to generate
+# path.
+#
+# mkuniqdir subdir new_dir_name
+mkuniqdir() {
+ local dir="$1"; local prefix="$2"
+ local retdir
+
+ retdir=$(funiq "${dir}" "${prefix}") || return 1
+ until mkdir "${retdir}" 2>/dev/null; do
+ retdir=$(funiq "${dir}" "${prefix}") || return 1
+ done
+
+ echo "${retdir}"
+}
+
+# Encodes non-printable characters and spaces in a string to their hexadecimal
+# values prefixed with '\x'.
+#
+# enc_nonprn_white str
+enc_nonprn_white() {
+ local str="$1"; local i=1
+
+ while [ $i -le 32 ]; do
+ str="$(str_replace "${str}" "$(chr $i)" \\x$(printf '%02x' $i))"
+ i=$(($i+1))
+ done
+
+ echo "${str}"
+}
+
+# Evaluates command for UUIDs either given as arguments for this function or all
# listed in /dev/disk/by-uuid. UUIDs doesn't have to be fully specified. If
-# beginning is given it is expanded to all matching UUIDs. To pass full UUID
-# to your command use '${full_uuid}'. Remember to escape '$'!
+# beginning is given it is expanded to all matching UUIDs. To pass full UUID to
+# your command use '$___' as a place holder. Remember to escape '$'!
+#
+# foreach_uuid_until [ -p prefix ] command UUIDs
#
-# $1 = command to be evaluated
-# $2 = list of UUIDs separated by space
+# prefix - string to put just before $___
+# command - command to be evaluated
+# UUIDs - list of UUIDs separated by space
#
# The function returns after *first successful evaluation* of the given command
# with status 0. If evaluation fails for every UUID function returns with
# status 1.
#
# Example:
-# foreach_uuid_until "mount -U \${full_uuid} /mnt; echo OK; umount /mnt" \
+# foreach_uuid_until "mount -U \$___ /mnt; echo OK; umount /mnt" \
# "01234 f512 a235567f-12a3-c123-a1b1-01234567abcb"
foreach_uuid_until() (
cd /dev/disk/by-uuid
+ [ "$1" = -p ] && local prefix="$2" && shift 2
local cmd="$1"; shift; local uuids_list="$*"
- local uuid; local full_uuid
+ local uuid; local full_uuid; local ___
[ -n "${cmd}" ] || return 1
for uuid in ${uuids_list:-*}; do
for full_uuid in ${uuid}*; do
[ -e "${full_uuid}" ] || continue
+ ___="${prefix}${full_uuid}"
eval ${cmd} && return 0
done
done
return 1
)
+
+# Evaluates command for every given device. Every single device must be
+# specified either by path, by label prefixed with 'LABEL=' or UUID prefixed
+# with 'UUID='. UUIDs are processed by 'foreach_uuid_until'. List elements'
+# order is preserved.
+#
+# foreach_dev_until command device1 device2 ...
+#
+# The function returns after *first successful evaluation* of the given command
+# with status 0. If evaluation fails for every device, function returns with
+# status 1.
+#
+# Example:
+# foreach_dev_until "echo \$___; false" /dev/sda1 "LABEL=Linux boot" "UUID=123a"
+foreach_dev_until() {
+ local cmd="$1"; shift
+ local dev; local ___
+
+ [ -n "${cmd}" ] || return 1
+
+ if [ -n "$*" ]; then
+ for dev; do
+ if str_starts "${dev}" 'UUID='; then
+ foreach_uuid_until -p 'UUID=' "${cmd}" "${dev#UUID=*}" && \
+ return 0
+ else
+ [ -e "${dev}" ] || [ -e "/dev/disk/by-label/$(enc_nonprn_white\
+ "${dev#LABEL=}")" ] || continue
+ ___="${dev}"
+ eval ${cmd} && return 0
+ fi
+ done
+ else
+ foreach_uuid_until -p 'UUID=' "${cmd}" && return 0
+ fi
+
+ return 1
+}
--
1.7.3
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 2/2] 90crypt: rem. key-media - support for labels and normal dev names
[not found] ` <1286145886-16322-1-git-send-email-aidecoe-2qtfh70TtYba5EbDDlwbIw@public.gmane.org>
@ 2010-10-03 22:44 ` Amadeusz Żołnowski
[not found] ` <1286145886-16322-2-git-send-email-aidecoe-2qtfh70TtYba5EbDDlwbIw@public.gmane.org>
0 siblings, 1 reply; 6+ messages in thread
From: Amadeusz Żołnowski @ 2010-10-03 22:44 UTC (permalink / raw)
To: initramfs-u79uwXL29TY76Z2rM5mHXA
90crypt: scan for devices several times instead of just once
The patch introduces support for labels and normal dev names for
removable media storing key for LUKS. Previously only UUID was
possible. rd_LUKS_KEYDEV_UUID changes to rd_LUKS_KEYDEV which takes dev
names as in /etc/fstab (e.g.: rd_LUKS_KEYDEV=LABEL=boot).
It also fixes problem with devices not discovered on time by retrying
(for default 3 times with incrementing sleep period) the scan.
probe_keydev informs now which device it checks.
Moreover code (the rem. dev. part) is refactorized.
---
dracut.kernel.7.xml | 13 ++--
modules.d/90crypt/cryptroot-ask.sh | 108 +++++++++++++++++++++++-------------
modules.d/90crypt/install | 1 +
3 files changed, 77 insertions(+), 45 deletions(-)
diff --git a/dracut.kernel.7.xml b/dracut.kernel.7.xml
index 0dc1ce8..8c0ae6c 100644
--- a/dracut.kernel.7.xml
+++ b/dracut.kernel.7.xml
@@ -324,25 +324,24 @@ This parameter can be specified multiple times.</para>
</variablelist>
</refsect2>
<refsect2>
- <title>crypt LUKS - experimental removable keys support</title>
- <para>works only when plymouth module is not included</para>
+ <title>crypt LUKS - keys on removable device</title>
<variablelist>
<varlistentry>
<term>
<envar>rd_LUKS_KEYPATH=</envar>
- <replaceable><path to keyfile></replaceable>
+ <replaceable><path></replaceable>
</term>
<listitem>
- <para>path to keyfile inside remove device filesystem</para>
+ <para>Path to keyfile inside removable device filesystem. May be specified multiple times - all paths will be checked.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
- <envar>rd_LUKS_KEYDEV_UUID=</envar>
- <replaceable><rem. device uuid></replaceable>
+ <envar>rd_LUKS_KEYDEV=</envar>
+ <replaceable><device></replaceable>
</term>
<listitem>
- <para>UUID of removalbe device storing keyfile; UUID doesn't have to be exact just like for <envar>rd_LUKS_UUID</envar></para>
+ <para>Device storing keyfile. It might be normal path (/dev/sdc1) or label (LABEL="Linux boot") or UUID. UUID doesn't have to be exact just like for <envar>rd_LUKS_UUID</envar>. <envar>rd_LUKS_KEYDEV</envar> isn't required. If not specified all devices accessible by UUID will be probed for keys listed in <envar>rd_LUKS_KEYPATH</envar>s.</para>
</listitem>
</varlistentry>
</variablelist>
diff --git a/modules.d/90crypt/cryptroot-ask.sh b/modules.d/90crypt/cryptroot-ask.sh
index 45b5fe7..75f4bbc 100755
--- a/modules.d/90crypt/cryptroot-ask.sh
+++ b/modules.d/90crypt/cryptroot-ask.sh
@@ -57,54 +57,87 @@ fi
# Search key on external devices
#
-# Try to mount device specified by UUID and probe for existence of any of
-# the paths. On success return 0 and print "<uuid> <first-existing-path>",
-# otherwise return 1.
-# Function leaves mount point created.
+# Try to mount specified device (by path, by UUID or by label) and probe for
+# existence of any of the paths. On success return 0 and print
+# "<device>\t<first-existing-path>", otherwise return 1.
+#
+# probe_keydev LABEL="LUKS keys" /test.key /keys/test.key
probe_keydev() {
- local uuid="$1"; shift; local keypaths="$*"
- local ret=1; local mount_point=/mnt/keydev
+ local dev="$1"; shift
+ local ret=1; local mount_point=$(mkuniqdir /mnt keydev)
local path
- [ -n "${uuid}" -a -n "${keypaths}" ] || return 1
- [ -d ${mount_point} ] || mkdir -p "${mount_point}" || return 1
+ [ -n "${dev}" -a -n "$*" ] || return 1
+ [ -d "${mount_point}" ] || die 'Mount point does not exist!'
- if mount -r -U "${uuid}" "${mount_point}" 2>/dev/null >/dev/null; then
- for path in ${keypaths}; do
+ info "cryptroot-ask: Probing ${dev}..."
+ if mount -r "${dev}" "${mount_point}" >/dev/null 2>&1; then
+ for path in "$@"; do
if [ -f "${mount_point}/${path}" ]; then
- echo "${uuid} ${path}"
+ echo "${dev} ${path}"
ret=0
break
fi
done
+
+ umount "${mount_point}"
fi
- umount "${mount_point}" 2>/dev/null >/dev/null
+ rmdir "${mount_point}"
return ${ret}
}
-keypaths="$(getargs rd_LUKS_KEYPATH)"
-unset keydev_uuid keypath
-
-if [ -n "$keypaths" ]; then
- keydev_uuids="$(getargs rd_LUKS_KEYDEV_UUID)"
- [ -n "$keydev_uuids" ] || {
- warn 'No UUID of device storing LUKS key specified.'
- warn 'It is recommended to set rd_LUKS_KEYDEV_UUID.'
- warn 'Performing scan of *all* devices accessible by UUID...'
- }
- tmp=$(foreach_uuid_until "probe_keydev \$full_uuid $keypaths" \
- $keydev_uuids) && {
- keydev_uuid="${tmp%% *}"
- keypath="${tmp#* }"
- } || {
- warn "Key for $device not found."
- }
- unset tmp keydev_uuids
-fi
+# Search LUKS key for encrypted device.
+#
+# func. args:
+# $1 = encrypted device
+# $2 = tries (optional; default is 3)
+#
+# kernel cmdline args:
+# rd_LUKS_KEYPATH
+# rd_LUKS_KEYDEV
+#
+# returns 0 if search succeeded
+# returns 1 if search failed
+# returns 2 if search skipped (when rd_LUKS_KEYPATH not specified)
+search_key_for() {
+ local device="$1"; local tries="$2"
+ local keypaths="$(getargs rd_LUKS_KEYPATH)"; local keydevs
+
+ if [ -n "$keypaths" ]; then
+ keydevs="$(getargs rd_LUKS_KEYDEV)"
+ [ -n "$keydevs" ] || {
+ warn 'No device storing LUKS key specified.'
+ warn 'It is recommended to set rd_LUKS_KEYDEV (best by UUID).'
+ warn 'Performing scan of *all* devices accessible by UUID...'
+ }
+
+ { [ -z "$2" ] || [ $2 -lt 1 ]; } && tries=3
+ local i=0
+ while [ $i -lt 3 ]; do
+ sleep $i
+ # following outputs "$keydev\t$keypath" (on success only)
+ foreach_dev_until "probe_keydev \$___ $keypaths" $keydevs && \
+ return 0
+ warn "Key for $device not found. Trying again..."
+ i=$(($i+1))
+ done
+
+ return 1
+ fi
+
+ return 2
+}
+
+mkdir -p /mnt
+
+tmp=$(search_key_for $device) && {
+ keydev="${tmp%% *}"
+ keypath="${tmp#* }"
+}
+unset tmp
-unset keypaths
#
# Open LUKS device
@@ -112,14 +145,13 @@ unset keypaths
info "luksOpen $device $luksname"
-if [ -n "$keydev_uuid" ]; then
- mntp=/mnt/keydev
- mkdir -p "$mntp"
- mount -r -U "$keydev_uuid" "$mntp"
+if [ -n "$keydev" ]; then
+ mntp=$(mkuniqdir /mnt keydev)
+ mount -r "$keydev" "$mntp" || die 'Mounting rem. dev. failed!'
cryptsetup -d "$mntp/$keypath" luksOpen "$device" "$luksname"
umount "$mntp"
- rmdir -p "$mntp" 2>/dev/null
- unset mntp keypath keydev_uuid
+ rmdir "$mntp"
+ unset mntp keypath keydev
else
# Prompt for password with plymouth, if installed.
# Should we check if plymouthd is running?
diff --git a/modules.d/90crypt/install b/modules.d/90crypt/install
index a518bc3..e4dfa47 100755
--- a/modules.d/90crypt/install
+++ b/modules.d/90crypt/install
@@ -2,6 +2,7 @@
# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
# ex: ts=8 sw=4 sts=4 et filetype=sh
inst cryptsetup
+inst rmdir
inst "$moddir"/cryptroot-ask.sh /sbin/cryptroot-ask
inst_hook cmdline 30 "$moddir/parse-crypt.sh"
inst_hook pre-pivot 30 "$moddir/crypt-cleanup.sh"
--
1.7.3
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH 2/2] 90crypt: rem. key-media - support for labels and normal dev names
[not found] ` <1286145886-16322-2-git-send-email-aidecoe-2qtfh70TtYba5EbDDlwbIw@public.gmane.org>
@ 2010-10-12 16:37 ` Harald Hoyer
[not found] ` <4CB48EE0.8050101-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2010-10-12 17:00 ` Harald Hoyer
1 sibling, 1 reply; 6+ messages in thread
From: Harald Hoyer @ 2010-10-12 16:37 UTC (permalink / raw)
To: Amadeusz Żołnowski; +Cc: initramfs-u79uwXL29TY76Z2rM5mHXA
On 10/04/2010 12:44 AM, Amadeusz Żołnowski wrote:
> 90crypt: scan for devices several times instead of just once
+ while [ $i -lt 3 ]; do
+ sleep $i
I would make that more dynamic.. we have udev..
/sbin/cryptroot-ask could install itsself again in the initqueue like
parse-crypt.sh does, if the rd_LUKS_KEYDEV is not there yet.
What do you think?
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 2/2] 90crypt: rem. key-media - support for labels and normal dev names
[not found] ` <1286145886-16322-2-git-send-email-aidecoe-2qtfh70TtYba5EbDDlwbIw@public.gmane.org>
2010-10-12 16:37 ` Harald Hoyer
@ 2010-10-12 17:00 ` Harald Hoyer
[not found] ` <4CB49443.8070407-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
1 sibling, 1 reply; 6+ messages in thread
From: Harald Hoyer @ 2010-10-12 17:00 UTC (permalink / raw)
To: Amadeusz Żołnowski; +Cc: initramfs-u79uwXL29TY76Z2rM5mHXA
On 10/04/2010 12:44 AM, Amadeusz Żołnowski wrote:
> + foreach_dev_until "probe_keydev \$___ $keypaths" $keydevs&& \
> + return 0
$___ is a foreach_dev_until internal local var?
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 2/2] 90crypt: rem. key-media - support for labels and normal dev names
[not found] ` <4CB49443.8070407-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
@ 2010-10-12 17:02 ` Harald Hoyer
0 siblings, 0 replies; 6+ messages in thread
From: Harald Hoyer @ 2010-10-12 17:02 UTC (permalink / raw)
To: Amadeusz Żołnowski; +Cc: initramfs-u79uwXL29TY76Z2rM5mHXA
On 10/12/2010 07:00 PM, Harald Hoyer wrote:
> On 10/04/2010 12:44 AM, Amadeusz Żołnowski wrote:
>> + foreach_dev_until "probe_keydev \$___ $keypaths" $keydevs&& \
>> + return 0
>
> $___ is a foreach_dev_until internal local var?
Ah, ok...
# To pass full UUID to
# your command use '$___' as a place holder. Remember to escape '$'!
hmm, well.. ok..
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 2/2] 90crypt: rem. key-media - support for labels and normal dev names
[not found] ` <4CB48EE0.8050101-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
@ 2010-10-13 10:36 ` Amadeusz Żołnowski
0 siblings, 0 replies; 6+ messages in thread
From: Amadeusz Żołnowski @ 2010-10-13 10:36 UTC (permalink / raw)
To: Harald Hoyer; +Cc: initramfs
[-- Attachment #1: Type: text/plain, Size: 603 bytes --]
Excerpts from Harald Hoyer's message of Tue Oct 12 18:37:52 +0200 2010:
> On 10/04/2010 12:44 AM, Amadeusz Żołnowski wrote:
> > 90crypt: scan for devices several times instead of just once
>
> + while [ $i -lt 3 ]; do
> + sleep $i
>
> I would make that more dynamic.. we have udev..
>
> /sbin/cryptroot-ask could install itsself again in the initqueue like
> parse-crypt.sh does, if the rd_LUKS_KEYDEV is not there yet.
>
> What do you think?
Hm… good point, thanks. I'll improve it.
--
Amadeusz Żołnowski
PGP key fpr: C700 CEDE 0C18 212E 49DA 4653 F013 4531 E1DB FAB5
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 490 bytes --]
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2010-10-13 10:36 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-10-03 22:44 [PATCH 1/2] 99base/dracut-lib.sh: 7 new functions & 1 modified Amadeusz Żołnowski
[not found] ` <1286145886-16322-1-git-send-email-aidecoe-2qtfh70TtYba5EbDDlwbIw@public.gmane.org>
2010-10-03 22:44 ` [PATCH 2/2] 90crypt: rem. key-media - support for labels and normal dev names Amadeusz Żołnowski
[not found] ` <1286145886-16322-2-git-send-email-aidecoe-2qtfh70TtYba5EbDDlwbIw@public.gmane.org>
2010-10-12 16:37 ` Harald Hoyer
[not found] ` <4CB48EE0.8050101-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2010-10-13 10:36 ` Amadeusz Żołnowski
2010-10-12 17:00 ` Harald Hoyer
[not found] ` <4CB49443.8070407-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2010-10-12 17:02 ` Harald Hoyer
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.