All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Amadeusz Żołnowski" <aidecoe-2qtfh70TtYba5EbDDlwbIw@public.gmane.org>
To: initramfs-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Subject: [PATCH] 90crypt: keys on external devices support
Date: Tue, 13 Jul 2010 19:14:47 +0200	[thread overview]
Message-ID: <20100713191447.0d09d065@etiriah> (raw)

[-- Attachment #1: Type: text/plain, Size: 9266 bytes --]

99base/dracut-lib.sh: new fun.: getoptcomma, foreach_uuid_until
---
 modules.d/90crypt/cryptroot-ask.sh |  121 ++++++++++++++++++++++++++++--------
 modules.d/90crypt/parse-crypt.sh   |   45 +++++++++----
 modules.d/99base/dracut-lib.sh     |   57 +++++++++++++++++
 3 files changed, 182 insertions(+), 41 deletions(-)

diff --git a/modules.d/90crypt/cryptroot-ask.sh b/modules.d/90crypt/cryptroot-ask.sh
index a6a9af1..58bf667 100755
--- a/modules.d/90crypt/cryptroot-ask.sh
+++ b/modules.d/90crypt/cryptroot-ask.sh
@@ -26,40 +26,107 @@ fi
 
 if [ -f /etc/crypttab ] && ! getargs rd_NO_CRYPTTAB; then
     while read name dev rest; do
-	# ignore blank lines and comments
-	if [ -z "$name" -o "${name#\#}" != "$name" ]; then
-	    continue
-	fi
-
-	# UUID used in crypttab
-	if [ "${dev%%=*}" = "UUID" ]; then
-	    if [ "luks-${dev##UUID=}" = "$2" ]; then
-		luksname="$name"
-		break
-	    fi
-	
-	# path used in crypttab
-	else
-	    cdev=$(readlink -f $dev)
-	    mdev=$(readlink -f $device)
-	    if [ "$cdev" = "$mdev" ]; then
-		luksname="$name"
-		break
-	    fi
-	fi
+        # ignore blank lines and comments
+        if [ -z "$name" -o "${name#\#}" != "$name" ]; then
+            continue
+        fi
+
+        # UUID used in crypttab
+        if [ "${dev%%=*}" = "UUID" ]; then
+            if [ "luks-${dev##UUID=}" = "$2" ]; then
+                luksname="$name"
+                break
+            fi
+        
+        # path used in crypttab
+        else
+            cdev=$(readlink -f $dev)
+            mdev=$(readlink -f $device)
+            if [ "$cdev" = "$mdev" ]; then
+                luksname="$name"
+                break
+            fi
+        fi
     done < /etc/crypttab
     unset name dev rest
 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.
+probe_keydev() {
+    local uuid="$1"; shift; local keypaths="$*"
+    local ret=1; local mount_point=/mnt/keydev
+    local path
+
+    [ -n "${uuid}" -a -n "${keypaths}" ] || return 1
+    [ -d ${mount_point} ] || mkdir -p "${mount_point}" || return 1
+
+    if mount -r -U "${uuid}" "${mount_point}" 2>/dev/null >/dev/null; then
+        for path in ${keypaths}; do
+            if [ -f "${mount_point}/${path}" ]; then
+                echo "${uuid} ${path}"
+                ret=0
+                break
+            fi
+        done
+    fi
+
+    umount "${mount_point}" 2>/dev/null >/dev/null
+
+    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
+
+unset keypaths
+
+#
+# Open LUKS device
+#
+
 info "luksOpen $device $luksname"
-# flock against other interactive activities
-{ flock -s 9; 
-    echo -n "$device ($luksname) is password protected"
-    cryptsetup luksOpen -T1 $1 $luksname 
-} 9>/.console.lock
+
+if [ -n "$keydev_uuid" ]; then
+    mntp=/mnt/keydev
+    mkdir -p "$mntp"
+    mount -r -U "$keydev_uuid" "$mntp"
+    cryptsetup -d "$mntp/$keypath" luksOpen "$device" "$luksname"
+    umount "$mntp"
+    rmdir -p "$mntp" 2>/dev/null
+else
+    # flock against other interactive activities
+    { flock -s 9;
+        echo -n "$device ($luksname) is password protected"
+        cryptsetup luksOpen -T1 $1 $luksname
+    } 9>/.console.lock
+fi
 
 # mark device as asked
 >> /tmp/cryptroot-asked-$2
 
 exit 0
-# vim:ts=8:sw=4:sts=4:et
\ No newline at end of file
+# vim:ts=8:sw=4:sts=4:et
diff --git a/modules.d/90crypt/parse-crypt.sh b/modules.d/90crypt/parse-crypt.sh
index 04d9ecb..fce952d 100755
--- a/modules.d/90crypt/parse-crypt.sh
+++ b/modules.d/90crypt/parse-crypt.sh
@@ -4,23 +4,40 @@ if getarg rd_NO_LUKS; then
     rm -f /etc/udev/rules.d/70-luks.rules
 else
     {
-	echo 'SUBSYSTEM!="block", GOTO="luks_end"'
-	echo 'ACTION!="add|change", GOTO="luks_end"'
+        echo 'SUBSYSTEM!="block", GOTO="luks_end"'
+        echo 'ACTION!="add|change", GOTO="luks_end"'
     } > /etc/udev/rules.d/70-luks.rules
-    LUKS=$(getargs rd_LUKS_UUID=)
+
+    LUKS=$(getargs rd_LUKS_UUID)
+    unset settled
+    [ -n "$(getargs rd_LUKS_KEYPATH)" ] && \
+            [ -z "$(getargs rd_LUKS_KEYDEV_UUID)" ] && \
+            settled='--settled'
+
     if [ -n "$LUKS" ]; then
-	echo '. /lib/dracut-lib.sh' > /emergency/crypt.sh
-	for luksid in $LUKS; do 
-	printf 'ENV{ID_FS_TYPE}=="crypto_LUKS", ENV{ID_FS_UUID}=="*%s*", RUN+="/sbin/initqueue --unique --onetime --name cryptroot-ask-%%k /sbin/cryptroot-ask $env{DEVNAME} luks-$env{ID_FS_UUID}"\n' $luksid \
-	    >> /etc/udev/rules.d/70-luks.rules	
-	printf '[ -e /dev/disk/by-uuid/*%s* ] || exit 1 \n'  $luksid >> /initqueue-finished/crypt.sh
-	printf '[ -e /dev/disk/by-uuid/*%s* ] || warn "crypto LUKS UUID "%s" not found" \n' $luksid $luksid >> /emergency/00-crypt.sh
-	done
+        echo '. /lib/dracut-lib.sh' > /emergency/crypt.sh
+        for luksid in $LUKS; do 
+            {
+                printf 'ENV{ID_FS_TYPE}=="crypto_LUKS", '
+                printf 'ENV{ID_FS_UUID}=="*%s*", ' $luksid
+                printf 'RUN+="/sbin/initqueue --unique --onetime %s ' "$settled"
+                printf '--name cryptroot-ask-%%k /sbin/cryptroot-ask '
+                printf '$env{DEVNAME} luks-$env{ID_FS_UUID}"\n'
+            } >> /etc/udev/rules.d/70-luks.rules
+
+            printf '[ -e /dev/disk/by-uuid/*%s* ] || exit 1\n' $luksid \
+                    >> /initqueue-finished/crypt.sh
+            {
+                printf '[ -e /dev/disk/by-uuid/*%s* ] || ' $luksid
+                printf 'warn "crypto LUKS UUID "%s" not found"\n' $luksid
+            } >> /emergency/00-crypt.sh
+        done
     else
-	echo 'ENV{ID_FS_TYPE}=="crypto_LUKS", RUN+="/sbin/initqueue --unique --onetime --name cryptroot-ask-%k /sbin/cryptroot-ask $env{DEVNAME} luks-$env{ID_FS_UUID}"' \
-	    >> /etc/udev/rules.d/70-luks.rules	
+        echo 'ENV{ID_FS_TYPE}=="crypto_LUKS", RUN+="/sbin/initqueue' $settled \
+                '--unique --onetime --name cryptroot-ask-%k' \
+                '/sbin/cryptroot-ask $env{DEVNAME} luks-$env{ID_FS_UUID}"' \
+                >> /etc/udev/rules.d/70-luks.rules
     fi
-    echo 'LABEL="luks_end"' >> /etc/udev/rules.d/70-luks.rules
 
+    echo 'LABEL="luks_end"' >> /etc/udev/rules.d/70-luks.rules
 fi
-
diff --git a/modules.d/99base/dracut-lib.sh b/modules.d/99base/dracut-lib.sh
index 2624f7d..84bb5fa 100755
--- a/modules.d/99base/dracut-lib.sh
+++ b/modules.d/99base/dracut-lib.sh
@@ -48,6 +48,31 @@ getargs() {
     return 1;
 }
 
+# Prints value of given option.  If option is a flag and it's present,
+# it just returns 0.  Otherwise 1 is returned.
+# $1 = options separated by commas
+# $2 = option we are interested in
+# 
+# Example:
+# $1 = cipher=aes-cbc-essiv:sha256,hash=sha256,verify
+# $2 = hash
+# Output:
+# sha256
+getoptcomma() {
+    local line=",$1,"; local opt="$2"; local tmp
+
+    case "${line}" in
+        *,${opt}=*,*)
+            tmp="${line#*,${opt}=}"
+            echo "${tmp%%,*}"
+            return 0
+        ;;
+        *,${opt},*) return 0 ;;
+    esac
+
+    return 1
+}
+
 setdebug() {
     if [ -z "$RDDEBUG" ]; then
         if [ -e /proc/cmdline ]; then
@@ -243,3 +268,35 @@ ip_to_var() {
     esac
 }
 
+# Evaluate 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 '$'!
+#
+# $1 = command to be evaluated
+# $2 = 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" \
+#       "01234 f512 a235567f-12a3-c123-a1b1-01234567abcb"
+foreach_uuid_until() (
+    cd /dev/disk/by-uuid
+
+    local cmd="$1"; shift; local uuids_list="$*"
+    local uuid; local full_uuid
+
+    [ -n "${cmd}" ] || return 1
+
+    for uuid in ${uuids_list:-*}; do
+        for full_uuid in ${uuid}*; do
+            [ -e "${full_uuid}" ] || continue
+            eval ${cmd} && return 0
+        done
+    done
+
+    return 1
+)
-- 
1.7.1

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 198 bytes --]

             reply	other threads:[~2010-07-13 17:14 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-07-13 17:14 Amadeusz Żołnowski [this message]
2010-07-21 11:41 ` [PATCH] 90crypt: keys on external devices support Harald Hoyer
  -- strict thread matches above, loose matches on Subject: below --
2010-10-19 13:54 Mr Dash Four
     [not found] ` <4CBDA328.40401-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>
2010-10-19 14:19   ` Amadeusz Żołnowski
2010-10-19 14:33     ` Mr Dash Four
     [not found]       ` <4CBDAC3D.7050906-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>
2010-10-20  1:24         ` Mr Dash Four
     [not found]           ` <4CBE44D3.6070000-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>
2010-10-20 14:12             ` Amadeusz Żołnowski
2010-10-20 14:44               ` Mr Dash Four
     [not found]                 ` <4CBF004F.9070201-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>
2010-10-20 15:17                   ` Amadeusz Żołnowski
2010-10-20 15:37                     ` Mr Dash Four
     [not found]                       ` <4CBF0CA3.1070801-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>
2010-10-22 16:51                         ` Amadeusz Żołnowski
2010-10-21 13:29                     ` Karel Zak
     [not found]                       ` <20101021132916.GC22186-sHeGUpI7y9L/9pzu0YdTqQ@public.gmane.org>
2010-10-21 13:54                         ` Mr Dash Four
     [not found]                           ` <4CC0462E.20507-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>
2010-10-21 15:18                             ` Karel Zak
     [not found]                               ` <20101021151802.GD22186-sHeGUpI7y9L/9pzu0YdTqQ@public.gmane.org>
2010-10-21 15:48                                 ` Mr Dash Four
     [not found]                                   ` <4CC060B3.3050508-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>
2010-10-22 16:40                                     ` Amadeusz Żołnowski
2010-10-22 18:34                                     ` Karel Zak
2010-10-20 13:19         ` Amadeusz Żołnowski
2010-10-20 14:06           ` Mr Dash Four
     [not found]             ` <4CBEF768.90908-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>
2010-10-20 14:25               ` Amadeusz Żołnowski
2010-10-20 14:48                 ` Mr Dash Four
     [not found]                   ` <4CBF0133.2070709-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>
2010-10-20 15:26                     ` Amadeusz Żołnowski
2010-10-20 15:39                       ` Mr Dash Four
2010-10-22 11:50                       ` Mr Dash Four
     [not found]                         ` <4CC17A87.7050804-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>
2010-10-22 17:07                           ` Amadeusz Żołnowski
2010-10-23 15:13                             ` Mr Dash Four

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20100713191447.0d09d065@etiriah \
    --to=aidecoe-2qtfh70ttyba5ebddlwbiw@public.gmane.org \
    --cc=initramfs-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.