chiark / gitweb /
mkaptsrc: Perl's scoping for named subroutines is bobbins.
[distorted-bits] / unlock-root
1 #! /bin/sh
2 ###
3 ### unlock-root KEY-FILE
4
5 set -e
6
7 ## Fetch the argument.
8 case $# in
9   1) keyfile=$1 ;;
10   *) echo >&2 "Usage: $0 KEY-FILE"; exit 16 ;;
11 esac
12
13 ## Some preflight checks.
14 if [ ! -x /usr/bin/gpg ]; then
15   echo >&2 "$0: can't find GnuPG executable"
16   exit 8
17 fi
18
19 ## Arrange to have somewhere for the key token.
20 mkdir -p /mnt/keys
21
22 ## Now we try to find a token.
23 lastuuid=no-match
24 prompt=t
25 win=nil
26 while :; do
27
28   ## Wait for a different device to be inserted.  The first time through,
29   ## we'll accept any device.
30   while :; do
31
32     ## If there's a token already inserted then go with that.
33     if info=$(blkid -o full -t LABEL=keys); then
34       eval DEVICE=$info
35       case "$UUID" in
36         "$lastuuid") ;;
37         *) lastuuid=$UUID; break ;;
38       esac
39     else
40       lastuuid=no-token
41     fi
42
43     ## Otherwise we could be here for a while.
44     case "$prompt" in
45       t) echo >&2 -n "Waiting for key token..."; prompt=nil ;;
46     esac
47
48     ## Wait for a bit.
49     sleep 1
50     udevadm settle
51   done
52
53   ## Mount the device somewhere.
54   mount -o ro -t ext2 UUID="$UUID" /mnt/keys
55
56   ## If we have the key file, then we're done.
57   if [ -f /mnt/keys/"$keyfile".gpg ]; then
58     
59     ## Update the eyecandy, such as it is.
60     case "$prompt" in
61       nil) >&2 echo " ok"; prompt=t ;;
62     esac
63
64     ## Get GnuPG to decrypt the key.  The enormous `gpg' rune is taken from
65     ## the cryptsetup `decrypt_gnupg' script.  The here-document prevents
66     ## the key ending up in a ps(1) listing, though the expected use-case is
67     ## to run this script from an initramfs so there won't be anyone
68     ## watching.
69     while :; do
70       key=$(/lib/cryptsetup/askpass "Enter passphrase for key $1: ")
71       case "$key" in "") break ;; esac
72       if /usr/bin/gpg -q --batch --no-options --no-mdc-warning  \
73                 --no-random-seed-file --no-default-keyring \
74                 --keyring /dev/null --secret-keyring /dev/null \
75                 --trustdb-name /dev/null --passphrase-fd 0 --decrypt \
76                 /mnt/keys/"$keyfile".gpg <<EOF
77 $key
78 EOF
79       then win=t; break; fi
80     done
81   fi
82
83   ## Unmount the filesystem.
84   umount /mnt/keys
85
86   ## If we did anything, stop.
87   case "$win" in t) break ;; esac
88 done
89
90 ## Done.
91 exit 0