reformat source code
[platform/upstream/dracut.git] / modules.d / 90crypt / cryptroot-ask.sh
1 #!/bin/sh
2 # -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
3 # ex: ts=8 sw=4 sts=4 et filetype=sh
4
5 # do not ask, if we already have root
6 [ -f /sysroot/proc ] && exit 0
7
8 # check if destination already exists
9 [ -b /dev/mapper/$2 ] && exit 0
10
11 # we already asked for this device
12 [ -f /tmp/cryptroot-asked-$2 ] && exit 0
13
14 # load dm_crypt if it is not already loaded
15 [ -d /sys/module/dm_crypt ] || modprobe dm_crypt
16
17 . /lib/dracut-lib.sh
18
19 # default luksname - luks-UUID
20 luksname=$2
21
22 # if device name is /dev/dm-X, convert to /dev/mapper/name
23 if [ "${1##/dev/dm-}" != "$1" ]; then
24     device="/dev/mapper/$(dmsetup info -c --noheadings -o name "$1")"
25 else
26     device="$1"
27 fi
28
29 if [ -f /etc/crypttab ] && ! getarg rd_NO_CRYPTTAB; then
30     while read name dev rest; do
31         # ignore blank lines and comments
32         if [ -z "$name" -o "${name#\#}" != "$name" ]; then
33             continue
34         fi
35
36         # UUID used in crypttab
37         if [ "${dev%%=*}" = "UUID" ]; then
38             if [ "luks-${dev##UUID=}" = "$2" ]; then
39                 luksname="$name"
40                 break
41             fi
42             
43         # path used in crypttab
44         else
45             cdev=$(readlink -f $dev)
46             mdev=$(readlink -f $device)
47             if [ "$cdev" = "$mdev" ]; then
48                 luksname="$name"
49                 break
50             fi
51         fi
52     done < /etc/crypttab
53     unset name dev rest
54 fi
55
56 #
57 # Search key on external devices
58 #
59
60 # Try to mount device specified by UUID and probe for existence of any of
61 # the paths.  On success return 0 and print "<uuid> <first-existing-path>",
62 # otherwise return 1.
63 # Function leaves mount point created.
64 probe_keydev() {
65     local uuid="$1"; shift; local keypaths="$*"
66     local ret=1; local mount_point=/mnt/keydev
67     local path
68
69     [ -n "${uuid}" -a -n "${keypaths}" ] || return 1
70     [ -d ${mount_point} ] || mkdir -p "${mount_point}" || return 1
71
72     if mount -r -U "${uuid}" "${mount_point}" 2>/dev/null >/dev/null; then
73         for path in ${keypaths}; do
74             if [ -f "${mount_point}/${path}" ]; then
75                 echo "${uuid} ${path}"
76                 ret=0
77                 break
78             fi
79         done
80     fi
81
82     umount "${mount_point}" 2>/dev/null >/dev/null
83
84     return ${ret}
85 }
86
87 keypaths="$(getargs rd_LUKS_KEYPATH)"
88 unset keydev_uuid keypath
89
90 if [ -n "$keypaths" ]; then
91     keydev_uuids="$(getargs rd_LUKS_KEYDEV_UUID)"
92     [ -n "$keydev_uuids" ] || {
93         warn 'No UUID of device storing LUKS key specified.'
94         warn 'It is recommended to set rd_LUKS_KEYDEV_UUID.'
95         warn 'Performing scan of *all* devices accessible by UUID...'
96     }
97     tmp=$(foreach_uuid_until "probe_keydev \$full_uuid $keypaths" \
98         $keydev_uuids) && {
99         keydev_uuid="${tmp%% *}"
100         keypath="${tmp#* }"
101     } || {
102         warn "Key for $device not found."
103     }
104     unset tmp keydev_uuids
105 fi
106
107 unset keypaths
108
109 #
110 # Open LUKS device
111 #
112
113 info "luksOpen $device $luksname"
114
115 if [ -n "$keydev_uuid" ]; then
116     mntp=/mnt/keydev
117     mkdir -p "$mntp"
118     mount -r -U "$keydev_uuid" "$mntp"
119     cryptsetup -d "$mntp/$keypath" luksOpen "$device" "$luksname"
120     umount "$mntp"
121     rmdir -p "$mntp" 2>/dev/null
122     unset mntp keypath keydev_uuid
123 else
124     # Prompt for password with plymouth, if installed.
125     # Should we check if plymouthd is running?
126     if [ -x /bin/plymouth ]; then
127         prompt="Password [$device ($luksname)]:" 
128         if [ ${#luksname} -gt 8 ]; then
129             sluksname=${sluksname##luks-}
130             sluksname=${luksname%%${luksname##????????}}
131             prompt="Password for $device ($sluksname...)"
132         fi
133         
134         # flock against other interactive activities
135         { flock -s 9; 
136             /bin/plymouth ask-for-password \
137                 --prompt "$prompt" \
138                 --command="/sbin/cryptsetup luksOpen -T1 $device $luksname"
139         } 9>/.console.lock
140         
141         unset sluksname prompt
142         
143     else
144         # flock against other interactive activities
145         { flock -s 9;
146             echo "$device ($luksname) is password protected"
147             cryptsetup luksOpen -T5 $device $luksname
148         } 9>/.console.lock
149     fi
150 fi
151
152 unset device luksname
153
154 # mark device as asked
155 >> /tmp/cryptroot-asked-$2
156
157 udevsettle
158
159 exit 0